diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java index ccdb00b65..e55c5a446 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java @@ -7,6 +7,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.SetUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.func.Editor; +import cn.hutool.core.lang.mutable.MutableEntry; import cn.hutool.core.map.CaseInsensitiveMap; import cn.hutool.core.map.MapUtil; import cn.hutool.core.reflect.ClassUtil; @@ -399,7 +400,7 @@ public class BeanUtil { * @return Bean */ public static T fillBeanWithMap(final Map map, final T bean, final boolean isToCamelCase, final boolean isIgnoreError) { - return fillBeanWithMap(map, bean, isToCamelCase, CopyOptions.create().setIgnoreError(isIgnoreError)); + return fillBeanWithMap(map, bean, isToCamelCase, CopyOptions.of().setIgnoreError(isIgnoreError)); } /** @@ -412,7 +413,7 @@ public class BeanUtil { * @return Bean */ public static T fillBeanWithMapIgnoreCase(final Map map, final T bean, final boolean isIgnoreError) { - return fillBeanWithMap(map, bean, CopyOptions.create().setIgnoreCase(true).setIgnoreError(isIgnoreError)); + return fillBeanWithMap(map, bean, CopyOptions.of().setIgnoreCase(true).setIgnoreError(isIgnoreError)); } /** @@ -527,15 +528,19 @@ public class BeanUtil { */ public static Map beanToMap(final Object bean, final String... properties) { int mapSize = 16; - Editor keyEditor = null; + Editor> editor = null; if (ArrayUtil.isNotEmpty(properties)) { mapSize = properties.length; final Set propertiesSet = SetUtil.of(properties); - keyEditor = property -> propertiesSet.contains(property) ? property : null; + editor = entry -> { + final String key = entry.getKey(); + entry.setKey(propertiesSet.contains(key) ? key : null); + return entry; + }; } // 指明了要复制的属性 所以不忽略null值 - return beanToMap(bean, new LinkedHashMap<>(mapSize, 1), false, keyEditor); + return beanToMap(bean, new LinkedHashMap<>(mapSize, 1), false, editor); } /** @@ -568,7 +573,11 @@ public class BeanUtil { return null; } - return beanToMap(bean, targetMap, ignoreNullValue, key -> isToUnderlineCase ? StrUtil.toUnderlineCase(key) : key); + return beanToMap(bean, targetMap, ignoreNullValue, entry -> { + final String key = entry.getKey(); + entry.setKey(isToUnderlineCase ? StrUtil.toUnderlineCase(key) : key); + return entry; + }); } /** @@ -588,15 +597,16 @@ public class BeanUtil { * @return Map * @since 4.0.5 */ - public static Map beanToMap(final Object bean, final Map targetMap, final boolean ignoreNullValue, final Editor keyEditor) { + public static Map beanToMap(final Object bean, final Map targetMap, + final boolean ignoreNullValue, final Editor> keyEditor) { if (null == bean) { return null; } return BeanCopier.create(bean, targetMap, - CopyOptions.create() + CopyOptions.of() .setIgnoreNullValue(ignoreNullValue) - .setFieldNameEditor(keyEditor) + .setFieldEditor(keyEditor) ).copy(); } @@ -642,7 +652,7 @@ public class BeanUtil { return null; } final T target = ConstructorUtil.newInstanceIfPossible(tClass); - copyProperties(source, target, CopyOptions.create().setIgnoreProperties(ignoreProperties)); + copyProperties(source, target, CopyOptions.of().setIgnoreProperties(ignoreProperties)); return target; } @@ -655,7 +665,7 @@ public class BeanUtil { * @param ignoreProperties 不拷贝的的属性列表 */ public static void copyProperties(final Object source, final Object target, final String... ignoreProperties) { - copyProperties(source, target, CopyOptions.create().setIgnoreProperties(ignoreProperties)); + copyProperties(source, target, CopyOptions.of().setIgnoreProperties(ignoreProperties)); } /** @@ -666,7 +676,7 @@ public class BeanUtil { * @param ignoreCase 是否忽略大小写 */ public static void copyProperties(final Object source, final Object target, final boolean ignoreCase) { - BeanCopier.create(source, target, CopyOptions.create().setIgnoreCase(ignoreCase)).copy(); + BeanCopier.create(source, target, CopyOptions.of().setIgnoreCase(ignoreCase)).copy(); } /** @@ -681,7 +691,7 @@ public class BeanUtil { if (null == source || null == target) { return; } - BeanCopier.create(source, target, ObjUtil.defaultIfNull(copyOptions, CopyOptions::create)).copy(); + BeanCopier.create(source, target, ObjUtil.defaultIfNull(copyOptions, CopyOptions::of)).copy(); } /** @@ -720,7 +730,7 @@ public class BeanUtil { * @since 5.6.6 */ public static List copyToList(final Collection collection, final Class targetType) { - return copyToList(collection, targetType, CopyOptions.create()); + return copyToList(collection, targetType, CopyOptions.of()); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/AbsCopier.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/AbsCopier.java index 673d78c5a..7f6d49215 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/AbsCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/AbsCopier.java @@ -23,6 +23,6 @@ public abstract class AbsCopier implements Copier { public AbsCopier(final S source, final T target, final CopyOptions copyOptions) { this.source = source; this.target = target; - this.copyOptions = ObjUtil.defaultIfNull(copyOptions, CopyOptions::create); + this.copyOptions = ObjUtil.defaultIfNull(copyOptions, CopyOptions::of); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanToBeanCopier.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanToBeanCopier.java index 620d5b63d..fe6047cf9 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanToBeanCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanToBeanCopier.java @@ -3,6 +3,7 @@ package cn.hutool.core.bean.copier; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.PropDesc; import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.mutable.MutableEntry; import cn.hutool.core.reflect.TypeUtil; import java.lang.reflect.Type; @@ -53,30 +54,36 @@ public class BeanToBeanCopier extends AbsCopier { return; } - sFieldName = copyOptions.editFieldName(sFieldName); + // 检查源对象属性是否过滤属性 + Object sValue = sDesc.getValue(this.source); + if (false == copyOptions.testPropertyFilter(sDesc.getField(), sValue)) { + return; + } + + // 编辑键值对 + final MutableEntry entry = copyOptions.editField(sFieldName, sValue); + if(null == entry){ + return; + } + sFieldName = entry.getKey(); // 对key做转换,转换后为null的跳过 if (null == sFieldName) { return; } + sValue = entry.getValue(); // 检查目标字段可写性 + // 目标字段检查放在键值对编辑之后,因为键可能被编辑修改 final PropDesc tDesc = targetPropDescMap.get(sFieldName); if (null == tDesc || false == tDesc.isWritable(this.copyOptions.transientSupport)) { // 字段不可写,跳过之 return; } - // 检查源对象属性是否过滤属性 - Object sValue = sDesc.getValue(this.source); - if (false == copyOptions.testPropertyFilter(sDesc.getField(), sValue)) { - return; - } - // 获取目标字段真实类型并转换源值 final Type fieldType = TypeUtil.getActualType(this.targetType, tDesc.getFieldType()); //sValue = Convert.convertWithCheck(fieldType, sValue, null, this.copyOptions.ignoreError); sValue = this.copyOptions.convertField(fieldType, sValue); - sValue = copyOptions.editFieldValue(sFieldName, sValue); // 目标赋值 tDesc.setValue(this.target, sValue, copyOptions.ignoreNullValue, copyOptions.ignoreError, copyOptions.override); diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanToMapCopier.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanToMapCopier.java index c49c777f6..72647f8a0 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanToMapCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanToMapCopier.java @@ -3,6 +3,7 @@ package cn.hutool.core.bean.copier; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.PropDesc; import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.mutable.MutableEntry; import cn.hutool.core.reflect.TypeUtil; import java.lang.reflect.Type; @@ -52,24 +53,29 @@ public class BeanToMapCopier extends AbsCopier { return; } - sFieldName = copyOptions.editFieldName(sFieldName); - // 对key做转换,转换后为null的跳过 - if (null == sFieldName) { - return; - } - // 检查源对象属性是否过滤属性 Object sValue = sDesc.getValue(this.source); if (false == copyOptions.testPropertyFilter(sDesc.getField(), sValue)) { return; } + // 编辑键值对 + final MutableEntry entry = copyOptions.editField(sFieldName, sValue); + if(null == entry){ + return; + } + sFieldName = entry.getKey(); + // 对key做转换,转换后为null的跳过 + if (null == sFieldName) { + return; + } + sValue = entry.getValue(); + // 获取目标值真实类型并转换源值 final Type[] typeArguments = TypeUtil.getTypeArguments(this.targetType); if(null != typeArguments){ //sValue = Convert.convertWithCheck(typeArguments[1], sValue, null, this.copyOptions.ignoreError); sValue = this.copyOptions.convertField(typeArguments[1], sValue); - sValue = copyOptions.editFieldValue(sFieldName, sValue); } // 目标赋值 diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/CopyOptions.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/CopyOptions.java index e0b5e8f88..d0c3fc874 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/CopyOptions.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/CopyOptions.java @@ -5,6 +5,7 @@ import cn.hutool.core.convert.Converter; import cn.hutool.core.lang.func.Editor; import cn.hutool.core.lang.func.Func1; import cn.hutool.core.lang.func.LambdaUtil; +import cn.hutool.core.lang.mutable.MutableEntry; import cn.hutool.core.util.ArrayUtil; import java.io.Serializable; @@ -12,7 +13,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Type; import java.util.Map; import java.util.Set; -import java.util.function.BiFunction; import java.util.function.BiPredicate; /** @@ -36,11 +36,6 @@ public class CopyOptions implements Serializable { * 是否忽略空值,当源对象的值为null时,true: 忽略而不注入此值,false: 注入null */ protected boolean ignoreNullValue; - /** - * 属性过滤器,断言通过的属性才会被复制
- * 断言参数中Field为源对象的字段对象,如果源对象为Map,使用目标对象,Object为源对象的对应值 - */ - private BiPredicate propertiesFilter; /** * 是否忽略字段注入错误 */ @@ -50,14 +45,16 @@ public class CopyOptions implements Serializable { */ protected boolean ignoreCase; /** - * 字段属性编辑器,用于自定义属性转换规则,例如驼峰转下划线等
- * 规则为,{@link Editor#edit(Object)}属性为源对象的字段名称或key,返回值为目标对象的字段名称或key + * 属性过滤器,断言通过的属性才会被复制
+ * 断言参数中Field为源对象的字段对象,如果源对象为Map,使用目标对象,Object为源对象的对应值 */ - private Editor fieldNameEditor; + private BiPredicate propertiesFilter; + /** - * 字段属性值编辑器,用于自定义属性值转换规则,例如null转""等 + * 字段属性名和属性值编辑器,,用于自定义属性转换规则(例如驼峰转下划线等),自定义属性值转换规则(例如null转""等) */ - protected BiFunction fieldValueEditor; + protected Editor> fieldEditor; + /** * 是否支持transient关键字修饰和@Transient注解,如果支持,被修饰的字段或方法对应的字段将被忽略。 */ @@ -80,7 +77,7 @@ public class CopyOptions implements Serializable { * * @return 拷贝选项 */ - public static CopyOptions create() { + public static CopyOptions of() { return new CopyOptions(); } @@ -92,7 +89,7 @@ public class CopyOptions implements Serializable { * @param ignoreProperties 忽略的属性列表,设置一个属性列表,不拷贝这些属性值 * @return 拷贝选项 */ - public static CopyOptions create(final Class editable, final boolean ignoreNullValue, final String... ignoreProperties) { + public static CopyOptions of(final Class editable, final boolean ignoreNullValue, final String... ignoreProperties) { return new CopyOptions(editable, ignoreNullValue, ignoreProperties); } //endregion @@ -235,7 +232,11 @@ public class CopyOptions implements Serializable { * @return CopyOptions */ public CopyOptions setFieldMapping(final Map fieldMapping) { - return setFieldNameEditor((key -> fieldMapping.getOrDefault(key, key))); + return setFieldEditor(entry -> { + final String key = entry.getKey(); + entry.setKey(fieldMapping.getOrDefault(key, key)); + return entry; + }); } /** @@ -243,24 +244,12 @@ public class CopyOptions implements Serializable { * 此转换器只针对源端的字段做转换,请确认转换后与目标端字段一致
* 当转换后的字段名为null时忽略这个字段 * - * @param fieldNameEditor 字段属性编辑器,用于自定义属性转换规则,例如驼峰转下划线等 + * @param editor 字段属性编辑器,用于自定义属性转换规则,例如驼峰转下划线等 * @return CopyOptions * @since 5.4.2 */ - public CopyOptions setFieldNameEditor(final Editor fieldNameEditor) { - this.fieldNameEditor = fieldNameEditor; - return this; - } - - /** - * 设置字段属性值编辑器,用于自定义属性值转换规则,例如null转""等
- * - * @param fieldValueEditor 字段属性值编辑器,用于自定义属性值转换规则,例如null转""等 - * @return CopyOptions - * @since 5.7.15 - */ - public CopyOptions setFieldValueEditor(final BiFunction fieldValueEditor) { - this.fieldValueEditor = fieldValueEditor; + public CopyOptions setFieldEditor(final Editor> editor) { + this.fieldEditor = editor; return this; } @@ -272,9 +261,10 @@ public class CopyOptions implements Serializable { * @return 编辑后的字段值 * @since 5.7.15 */ - protected Object editFieldValue(final String fieldName, final Object fieldValue) { - return (null != this.fieldValueEditor) ? - this.fieldValueEditor.apply(fieldName, fieldValue) : fieldValue; + protected MutableEntry editField(final String fieldName, final Object fieldValue) { + final MutableEntry entry = new MutableEntry<>(fieldName, fieldValue); + return (null != this.fieldEditor) ? + this.fieldEditor.edit(entry) : entry; } /** @@ -327,17 +317,6 @@ public class CopyOptions implements Serializable { this.converter.convert(targetType, fieldValue) : fieldValue; } - /** - * 转换字段名为编辑后的字段名 - * - * @param fieldName 字段名 - * @return 编辑后的字段名 - * @since 5.4.2 - */ - protected String editFieldName(final String fieldName) { - return (null != this.fieldNameEditor) ? this.fieldNameEditor.edit(fieldName) : fieldName; - } - /** * 测试是否保留字段,{@code true}保留,{@code false}不保留 * diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/MapToBeanCopier.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/MapToBeanCopier.java index 574589468..c1333de48 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/MapToBeanCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/MapToBeanCopier.java @@ -3,6 +3,7 @@ package cn.hutool.core.bean.copier; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.PropDesc; import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.mutable.MutableEntry; import cn.hutool.core.map.CaseInsensitiveMap; import cn.hutool.core.map.MapWrapper; import cn.hutool.core.text.StrUtil; @@ -61,30 +62,35 @@ public class MapToBeanCopier extends AbsCopier, T> { if (null == sKey) { return; } - String sKeyStr = copyOptions.editFieldName(sKey.toString()); + + // 编辑键值对 + final MutableEntry entry = copyOptions.editField(sKey.toString(), sValue); + if(null == entry){ + return; + } + String sFieldName = entry.getKey(); // 对key做转换,转换后为null的跳过 - if (null == sKeyStr) { + if (null == sFieldName) { return; } // 检查目标字段可写性 - final PropDesc tDesc = findPropDesc(targetPropDescMap, sKeyStr); + // 目标字段检查放在键值对编辑之后,因为键可能被编辑修改 + final PropDesc tDesc = findPropDesc(targetPropDescMap, sFieldName); if (null == tDesc || false == tDesc.isWritable(this.copyOptions.transientSupport)) { // 字段不可写,跳过之 return; } - sKeyStr = tDesc.getFieldName(); + Object newValue = entry.getValue(); // 检查目标是否过滤属性 - if (false == copyOptions.testPropertyFilter(tDesc.getField(), sValue)) { + if (false == copyOptions.testPropertyFilter(tDesc.getField(), newValue)) { return; } // 获取目标字段真实类型并转换源值 final Type fieldType = TypeUtil.getActualType(this.targetType, tDesc.getFieldType()); - //Object newValue = Convert.convertWithCheck(fieldType, sValue, null, this.copyOptions.ignoreError); - Object newValue = this.copyOptions.convertField(fieldType, sValue); - newValue = copyOptions.editFieldValue(sKeyStr, newValue); + newValue = this.copyOptions.convertField(fieldType, newValue); // 目标赋值 tDesc.setValue(this.target, newValue, copyOptions.ignoreNullValue, copyOptions.ignoreError, copyOptions.override); diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/MapToMapCopier.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/MapToMapCopier.java index a9cb20944..f0457a0e0 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/MapToMapCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/MapToMapCopier.java @@ -1,5 +1,6 @@ package cn.hutool.core.bean.copier; +import cn.hutool.core.lang.mutable.MutableEntry; import cn.hutool.core.reflect.TypeUtil; import java.lang.reflect.Type; @@ -37,13 +38,20 @@ public class MapToMapCopier extends AbsCopier { if (null == sKey) { return; } - final String sKeyStr = copyOptions.editFieldName(sKey.toString()); - // 对key做转换,转换后为null的跳过 - if (null == sKeyStr) { + + // 编辑键值对 + final MutableEntry entry = copyOptions.editField(sKey.toString(), sValue); + if(null == entry){ return; } + sKey = entry.getKey(); + // 对key做转换,转换后为null的跳过 + if (null == sKey) { + return; + } + sValue = entry.getValue(); - final Object targetValue = target.get(sKeyStr); + final Object targetValue = target.get(sKey); // 非覆盖模式下,如果目标值存在,则跳过 if (false == copyOptions.override && null != targetValue) { return; @@ -52,13 +60,11 @@ public class MapToMapCopier extends AbsCopier { // 获取目标值真实类型并转换源值 final Type[] typeArguments = TypeUtil.getTypeArguments(this.targetType); if(null != typeArguments){ - //sValue = Convert.convertWithCheck(typeArguments[1], sValue, null, this.copyOptions.ignoreError); sValue = this.copyOptions.convertField(typeArguments[1], sValue); - sValue = copyOptions.editFieldValue(sKeyStr, sValue); } // 目标赋值 - target.put(sKeyStr, sValue); + target.put(sKey, sValue); }); return this.target; } diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/ValueProviderToBeanCopier.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/ValueProviderToBeanCopier.java index 0277d2dc7..02ae48fcb 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/ValueProviderToBeanCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/ValueProviderToBeanCopier.java @@ -3,6 +3,7 @@ package cn.hutool.core.bean.copier; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.PropDesc; import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.mutable.MutableEntry; import cn.hutool.core.reflect.TypeUtil; import java.lang.reflect.Type; @@ -63,13 +64,23 @@ public class ValueProviderToBeanCopier extends AbsCopier entry = copyOptions.editField(tFieldName, sValue); + if(null == entry){ + return; + } + tFieldName = entry.getKey(); + // 对key做转换,转换后为null的跳过 + if (null == tFieldName) { + return; + } + sValue = entry.getValue(); // 检查目标对象属性是否过滤属性 - Object sValue = source.value(tFieldName, fieldType); if (false == copyOptions.testPropertyFilter(tDesc.getField(), sValue)) { return; } - sValue = copyOptions.editFieldValue(tFieldName, sValue); // 目标赋值 tDesc.setValue(this.target, sValue, copyOptions.ignoreNullValue, copyOptions.ignoreError, copyOptions.override); diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/BeanConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/BeanConverter.java index ebc5e5efd..86bdeacc9 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/BeanConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/BeanConverter.java @@ -38,7 +38,7 @@ public class BeanConverter implements Converter, Serializable { * 构造 */ public BeanConverter() { - this(CopyOptions.create().setIgnoreError(true)); + this(CopyOptions.of().setIgnoreError(true)); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/map/Dict.java b/hutool-core/src/main/java/cn/hutool/core/map/Dict.java index 89eb4f05e..ff8b563fd 100755 --- a/hutool-core/src/main/java/cn/hutool/core/map/Dict.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/Dict.java @@ -247,7 +247,7 @@ public class Dict extends LinkedHashMap implements BasicTypeGett * @return vo */ public T toBeanIgnoreCase(final Class clazz) { - return BeanUtil.toBean(this, clazz, CopyOptions.create().setIgnoreCase(true)); + return BeanUtil.toBean(this, clazz, CopyOptions.of().setIgnoreCase(true)); } /** diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/BeanCopyMappingTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/BeanCopyMappingTest.java index 702ba07f4..151419e48 100644 --- a/hutool-core/src/test/java/cn/hutool/core/bean/BeanCopyMappingTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanCopyMappingTest.java @@ -15,15 +15,17 @@ public class BeanCopyMappingTest { */ @Test public void copyPropertiesTest() { - final CopyOptions copyOptions = CopyOptions.create() + final CopyOptions copyOptions = CopyOptions.of() .setFieldMapping(MapUtil.of("car", "carNo")); + final B b = B.builder().car("12312312").build(); final A a = A.builder().build(); final C c = C.builder().build(); BeanUtil.copyProperties(b, a, copyOptions); BeanUtil.copyProperties(a, c); + Assert.assertEquals("12312312", a.getCarNo()); Assert.assertEquals("12312312", c.getCarNo()); } diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java index 77bfcc86d..8061d81ec 100755 --- a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java @@ -71,7 +71,7 @@ public class BeanUtilTest { return true; } - }, CopyOptions.create()); + }, CopyOptions.of()); Assert.assertEquals("张三", person.getName()); Assert.assertEquals(18, person.getAge()); @@ -116,7 +116,7 @@ public class BeanUtilTest { // 错误的类型,此处忽略 map.put("age", "aaaaaa"); - final Person person = BeanUtil.toBean(map, Person.class, CopyOptions.create().setIgnoreError(true)); + final Person person = BeanUtil.toBean(map, Person.class, CopyOptions.of().setIgnoreError(true)); Assert.assertEquals("Joe", person.getName()); // 错误的类型,不copy这个字段,使用对象创建的默认值 Assert.assertEquals(0, person.getAge()); @@ -128,7 +128,7 @@ public class BeanUtilTest { map.put("Name", "Joe"); map.put("aGe", 12); - final Person person = BeanUtil.toBean(map, Person.class, CopyOptions.create().setIgnoreCase(true)); + final Person person = BeanUtil.toBean(map, Person.class, CopyOptions.of().setIgnoreCase(true)); Assert.assertEquals("Joe", person.getName()); Assert.assertEquals(12, person.getAge()); } @@ -144,7 +144,7 @@ public class BeanUtilTest { mapping.put("a_name", "name"); mapping.put("b_age", "age"); - final Person person = BeanUtil.toBean(map, Person.class, CopyOptions.create().setFieldMapping(mapping)); + final Person person = BeanUtil.toBean(map, Person.class, CopyOptions.of().setFieldMapping(mapping)); Assert.assertEquals("Joe", person.getName()); Assert.assertEquals(12, person.getAge()); } @@ -159,7 +159,7 @@ public class BeanUtilTest { map.put("age", 12); // 非空构造也可以实例化成功 - final Person2 person = BeanUtil.toBean(map, Person2.class, CopyOptions.create()); + final Person2 person = BeanUtil.toBean(map, Person2.class, CopyOptions.of()); Assert.assertEquals("Joe", person.name); Assert.assertEquals(12, person.age); } @@ -229,7 +229,10 @@ public class BeanUtilTest { person.setSubName("sub名字"); final Map map = BeanUtil.beanToMap(person, new LinkedHashMap<>(), - CopyOptions.create().setFieldValueEditor((key, value) -> key + "_" + value)); + CopyOptions.of().setFieldEditor((entry) -> { + entry.setValue(entry.getKey() + "_" + entry.getValue()); + return entry; + })); Assert.assertEquals("subName_sub名字", map.get("subName")); } @@ -387,7 +390,7 @@ public class BeanUtilTest { p2.setName("oldName"); // null值不覆盖目标属性 - BeanUtil.copyProperties(p1, p2, CopyOptions.create().ignoreNullValue()); + BeanUtil.copyProperties(p1, p2, CopyOptions.of().ignoreNullValue()); Assert.assertEquals("oldName", p2.getName()); // null覆盖目标属性 @@ -578,7 +581,7 @@ public class BeanUtilTest { info.setBookID("0"); info.setCode(""); final Food newFood = new Food(); - final CopyOptions copyOptions = CopyOptions.create().setPropertiesFilter((f, v) -> !(v instanceof CharSequence) || StrUtil.isNotBlank(v.toString())); + final CopyOptions copyOptions = CopyOptions.of().setPropertiesFilter((f, v) -> !(v instanceof CharSequence) || StrUtil.isNotBlank(v.toString())); BeanUtil.copyProperties(info, newFood, copyOptions); Assert.assertEquals(info.getBookID(), newFood.getBookID()); Assert.assertNull(newFood.getCode()); @@ -592,7 +595,7 @@ public class BeanUtilTest { o.setAge(123); o.setOpenid("asd"); - @SuppressWarnings("unchecked") final CopyOptions copyOptions = CopyOptions.create().setIgnoreProperties(Person::getAge,Person::getOpenid); + @SuppressWarnings("unchecked") final CopyOptions copyOptions = CopyOptions.of().setIgnoreProperties(Person::getAge,Person::getOpenid); final Person n = new Person(); BeanUtil.copyProperties(o, n, copyOptions); @@ -680,7 +683,12 @@ public class BeanUtilTest { a, new LinkedHashMap<>(), false, - key -> Arrays.asList("id", "name", "code", "sortOrder").contains(key) ? key : null); + entry -> { + if(false == Arrays.asList("id", "name", "code", "sortOrder").contains(entry.getKey())){ + entry.setKey(null); + } + return entry; + }); Assert.assertFalse(f.containsKey(null)); } @@ -749,10 +757,13 @@ public class BeanUtilTest { childVo1.setChild_father_name("张无忌"); childVo1.setChild_mother_name("赵敏敏"); - final CopyOptions copyOptions = CopyOptions.create(). + final CopyOptions copyOptions = CopyOptions.of(). //setIgnoreNullValue(true). //setIgnoreCase(false). - setFieldNameEditor(StrUtil::toCamelCase); + setFieldEditor(entry->{ + entry.setKey(StrUtil.toCamelCase(entry.getKey())); + return entry; + }); final ChildVo2 childVo2 = new ChildVo2(); BeanUtil.copyProperties(childVo1, childVo2, copyOptions); @@ -783,7 +794,7 @@ public class BeanUtilTest { public void issueI41WKPTest(){ final Test1 t1 = new Test1().setStrList(ListUtil.of("list")); final Test2 t2_hu = new Test2(); - BeanUtil.copyProperties(t1, t2_hu, CopyOptions.create().setIgnoreError(true)); + BeanUtil.copyProperties(t1, t2_hu, CopyOptions.of().setIgnoreError(true)); Assert.assertNull(t2_hu.getStrList()); } diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/Issue1687Test.java b/hutool-core/src/test/java/cn/hutool/core/bean/Issue1687Test.java index 488405fc0..cfbddac83 100755 --- a/hutool-core/src/test/java/cn/hutool/core/bean/Issue1687Test.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/Issue1687Test.java @@ -33,7 +33,7 @@ public class Issue1687Test { sysUserFb.setCustomerId("456"); // 补救别名错位 - final CopyOptions copyOptions = CopyOptions.create().setFieldMapping( + final CopyOptions copyOptions = CopyOptions.of().setFieldMapping( MapUtil.builder("depart", "depId").build() ); final SysUser sysUser = BeanUtil.toBean(sysUserFb, SysUser.class, copyOptions); diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/Issue2202Test.java b/hutool-core/src/test/java/cn/hutool/core/bean/Issue2202Test.java index fb1433d1b..6ffd5f6e1 100755 --- a/hutool-core/src/test/java/cn/hutool/core/bean/Issue2202Test.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/Issue2202Test.java @@ -22,7 +22,10 @@ public class Issue2202Test { headerMap.put("wechatpay-timestamp", "timestamp"); headerMap.put("wechatpay-signature", "signature"); final ResponseSignVerifyParams case1 = BeanUtil.toBean(headerMap, ResponseSignVerifyParams.class, - CopyOptions.create().setFieldNameEditor(field -> NamingCase.toCamelCase(field, '-'))); + CopyOptions.of().setFieldEditor(entry -> { + entry.setKey(NamingCase.toCamelCase(entry.getKey(), '-')); + return entry; + })); Assert.assertEquals("serial", case1.getWechatpaySerial()); Assert.assertEquals("nonce", case1.getWechatpayNonce()); diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/copier/BeanCopierTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/copier/BeanCopierTest.java index 369631104..54a113c32 100644 --- a/hutool-core/src/test/java/cn/hutool/core/bean/copier/BeanCopierTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/copier/BeanCopierTest.java @@ -12,13 +12,13 @@ public class BeanCopierTest { public void beanToMapIgnoreNullTest() { final A a = new A(); - HashMap map = BeanCopier.create(a, new HashMap<>(), CopyOptions.create()).copy(); + HashMap map = BeanCopier.create(a, new HashMap<>(), CopyOptions.of()).copy(); Assert.assertEquals(1, map.size()); Assert.assertTrue(map.containsKey("value")); Assert.assertNull(map.get("value")); // 忽略null的情况下,空字段不写入map - map = BeanCopier.create(a, new HashMap<>(), CopyOptions.create().ignoreNullValue()).copy(); + map = BeanCopier.create(a, new HashMap<>(), CopyOptions.of().ignoreNullValue()).copy(); Assert.assertFalse(map.containsKey("value")); Assert.assertEquals(0, map.size()); } @@ -33,7 +33,7 @@ public class BeanCopierTest { final B b = new B(); b.setValue("abc"); - final BeanCopier copier = BeanCopier.create(a, b, CopyOptions.create().setOverride(false)); + final BeanCopier copier = BeanCopier.create(a, b, CopyOptions.of().setOverride(false)); copier.copy(); Assert.assertEquals("abc", b.getValue()); @@ -49,7 +49,7 @@ public class BeanCopierTest { final B b = new B(); b.setValue("abc"); - final BeanCopier copier = BeanCopier.create(a, b, CopyOptions.create()); + final BeanCopier copier = BeanCopier.create(a, b, CopyOptions.of()); copier.copy(); Assert.assertEquals("123", b.getValue()); diff --git a/hutool-extra/src/main/java/cn/hutool/extra/servlet/JakartaServletUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/servlet/JakartaServletUtil.java index 8a4347fc7..737cf7ca9 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/servlet/JakartaServletUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/servlet/JakartaServletUtil.java @@ -169,7 +169,7 @@ public class JakartaServletUtil { * @return Bean */ public static T fillBean(final ServletRequest request, final T bean, final boolean isIgnoreError) { - return fillBean(request, bean, CopyOptions.create().setIgnoreError(isIgnoreError)); + return fillBean(request, bean, CopyOptions.of().setIgnoreError(isIgnoreError)); } /** diff --git a/hutool-extra/src/main/java/cn/hutool/extra/servlet/ServletUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/servlet/ServletUtil.java index 312fb379b..2b3f6eed8 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/servlet/ServletUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/servlet/ServletUtil.java @@ -169,7 +169,7 @@ public class ServletUtil { * @return Bean */ public static T fillBean(final ServletRequest request, final T bean, final boolean isIgnoreError) { - return fillBean(request, bean, CopyOptions.create().setIgnoreError(isIgnoreError)); + return fillBean(request, bean, CopyOptions.of().setIgnoreError(isIgnoreError)); } /** diff --git a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java index f1000813a..869118446 100755 --- a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java @@ -184,7 +184,7 @@ public final class InternalJSONUtil { * @since 5.8.0 */ static CopyOptions toCopyOptions(final JSONConfig config) { - return CopyOptions.create() + return CopyOptions.of() .setIgnoreCase(config.isIgnoreCase()) .setIgnoreError(config.isIgnoreError()) .setIgnoreNullValue(config.isIgnoreNullValue()) diff --git a/hutool-json/src/main/java/cn/hutool/json/ObjectMapper.java b/hutool-json/src/main/java/cn/hutool/json/ObjectMapper.java index 30d9162ee..659b69c5e 100755 --- a/hutool-json/src/main/java/cn/hutool/json/ObjectMapper.java +++ b/hutool-json/src/main/java/cn/hutool/json/ObjectMapper.java @@ -1,6 +1,7 @@ package cn.hutool.json; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.collection.iter.ArrayIter; import cn.hutool.core.convert.Convert; import cn.hutool.core.io.IoUtil; @@ -110,8 +111,7 @@ public class ObjectMapper { mapFromResourceBundle((ResourceBundle) source, jsonObject, filter); } else if (BeanUtil.isReadableBean(source.getClass())) { // 普通Bean - // TODO 过滤器对Bean无效,需补充。 - mapFromBean(source, jsonObject); + mapFromBean(source, jsonObject, filter); } else { // 不支持对象类型转换为JSONObject throw new JSONException("Unsupported type [{}] to JSONObject!", source.getClass()); @@ -248,7 +248,9 @@ public class ObjectMapper { * @param bean Bean对象 * @param jsonObject {@link JSONObject} */ - private static void mapFromBean(final Object bean, final JSONObject jsonObject) { - BeanUtil.beanToMap(bean, jsonObject, InternalJSONUtil.toCopyOptions(jsonObject.getConfig())); + private static void mapFromBean(final Object bean, final JSONObject jsonObject, final Filter> filter) { + final CopyOptions copyOptions = InternalJSONUtil.toCopyOptions(jsonObject.getConfig()); + copyOptions.setFieldEditor((entry -> filter.accept(entry) ? entry : null)); + BeanUtil.beanToMap(bean, jsonObject, copyOptions); } } diff --git a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvRow.java b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvRow.java index c6a48a0f2..5d7b77bf9 100755 --- a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvRow.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvRow.java @@ -107,7 +107,7 @@ public final class CsvRow implements List { * @since 5.3.6 */ public T toBean(final Class clazz){ - return BeanUtil.toBean(getFieldMap(), clazz, CopyOptions.create().setIgnoreError(true)); + return BeanUtil.toBean(getFieldMap(), clazz, CopyOptions.of().setIgnoreError(true)); } /** diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/reader/BeanSheetReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/reader/BeanSheetReader.java index 2a0c6fb64..699a73167 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/reader/BeanSheetReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/reader/BeanSheetReader.java @@ -42,7 +42,7 @@ public class BeanSheetReader implements SheetReader> { } final List beanList = new ArrayList<>(mapList.size()); - final CopyOptions copyOptions = CopyOptions.create().setIgnoreError(true); + final CopyOptions copyOptions = CopyOptions.of().setIgnoreError(true); for (final Map map : mapList) { beanList.add(BeanUtil.toBean(map, this.beanClass, copyOptions)); } diff --git a/hutool-setting/src/main/java/cn/hutool/setting/AbsSetting.java b/hutool-setting/src/main/java/cn/hutool/setting/AbsSetting.java index db8a3f0a8..14420bdbe 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/AbsSetting.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/AbsSetting.java @@ -297,7 +297,7 @@ public abstract class AbsSetting implements OptNullBasicTypeFromStringGetter