This commit is contained in:
Looly 2022-06-07 15:31:55 +08:00
parent 084870261f
commit 9b9b35ffc2
22 changed files with 165 additions and 122 deletions

View File

@ -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> 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> 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<String, Object> beanToMap(final Object bean, final String... properties) {
int mapSize = 16;
Editor<String> keyEditor = null;
Editor<MutableEntry<String, Object>> editor = null;
if (ArrayUtil.isNotEmpty(properties)) {
mapSize = properties.length;
final Set<String> 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<String, Object> beanToMap(final Object bean, final Map<String, Object> targetMap, final boolean ignoreNullValue, final Editor<String> keyEditor) {
public static Map<String, Object> beanToMap(final Object bean, final Map<String, Object> targetMap,
final boolean ignoreNullValue, final Editor<MutableEntry<String, Object>> 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 <T> List<T> copyToList(final Collection<?> collection, final Class<T> targetType) {
return copyToList(collection, targetType, CopyOptions.create());
return copyToList(collection, targetType, CopyOptions.of());
}
/**

View File

@ -23,6 +23,6 @@ public abstract class AbsCopier<S, T> implements Copier<T> {
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);
}
}

View File

@ -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<S, T> extends AbsCopier<S, T> {
return;
}
sFieldName = copyOptions.editFieldName(sFieldName);
// 检查源对象属性是否过滤属性
Object sValue = sDesc.getValue(this.source);
if (false == copyOptions.testPropertyFilter(sDesc.getField(), sValue)) {
return;
}
// 编辑键值对
final MutableEntry<String, Object> 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);

View File

@ -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<Object, Map> {
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<String, Object> 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);
}
// 目标赋值

View File

@ -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;
/**
* 属性过滤器断言通过的属性才会被复制<br>
* 断言参数中Field为源对象的字段对象,如果源对象为Map使用目标对象Object为源对象的对应值
*/
private BiPredicate<Field, Object> propertiesFilter;
/**
* 是否忽略字段注入错误
*/
@ -50,14 +45,16 @@ public class CopyOptions implements Serializable {
*/
protected boolean ignoreCase;
/**
* 字段属性编辑器用于自定义属性转换规则例如驼峰转下划线等<br>
* 规则为{@link Editor#edit(Object)}属性为源对象的字段名称或key返回值为目标对象的字段名称或key
* 属性过滤器断言通过的属性才会被复制<br>
* 断言参数中Field为源对象的字段对象,如果源对象为Map使用目标对象Object为源对象的对应值
*/
private Editor<String> fieldNameEditor;
private BiPredicate<Field, Object> propertiesFilter;
/**
* 字段属性值编辑器用于自定义属性值转换规则例如null转""
* 字段属性名和属性值编辑器用于自定义属性转换规则例如驼峰转下划线等自定义属性值转换规则例如null转""
*/
protected BiFunction<String, Object, Object> fieldValueEditor;
protected Editor<MutableEntry<String, Object>> 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<String, String> 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 {
* 此转换器只针对源端的字段做转换请确认转换后与目标端字段一致<br>
* 当转换后的字段名为null时忽略这个字段
*
* @param fieldNameEditor 字段属性编辑器用于自定义属性转换规则例如驼峰转下划线等
* @param editor 字段属性编辑器用于自定义属性转换规则例如驼峰转下划线等
* @return CopyOptions
* @since 5.4.2
*/
public CopyOptions setFieldNameEditor(final Editor<String> fieldNameEditor) {
this.fieldNameEditor = fieldNameEditor;
return this;
}
/**
* 设置字段属性值编辑器用于自定义属性值转换规则例如null转""<br>
*
* @param fieldValueEditor 字段属性值编辑器用于自定义属性值转换规则例如null转""
* @return CopyOptions
* @since 5.7.15
*/
public CopyOptions setFieldValueEditor(final BiFunction<String, Object, Object> fieldValueEditor) {
this.fieldValueEditor = fieldValueEditor;
public CopyOptions setFieldEditor(final Editor<MutableEntry<String, Object>> 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<String, Object> editField(final String fieldName, final Object fieldValue) {
final MutableEntry<String, Object> 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}不保留
*

View File

@ -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<T> extends AbsCopier<Map<?, ?>, T> {
if (null == sKey) {
return;
}
String sKeyStr = copyOptions.editFieldName(sKey.toString());
// 编辑键值对
final MutableEntry<String, Object> 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);

View File

@ -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<Map, Map> {
if (null == sKey) {
return;
}
final String sKeyStr = copyOptions.editFieldName(sKey.toString());
// 对key做转换转换后为null的跳过
if (null == sKeyStr) {
// 编辑键值对
final MutableEntry<String, Object> 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<Map, Map> {
// 获取目标值真实类型并转换源值
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;
}

View File

@ -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<T> extends AbsCopier<ValueProvider<String
// 获取目标字段真实类型
final Type fieldType = TypeUtil.getActualType(this.targetType ,tDesc.getFieldType());
Object sValue = source.value(tFieldName, fieldType);
// 编辑键值对
final MutableEntry<String, Object> 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);

View File

@ -38,7 +38,7 @@ public class BeanConverter implements Converter, Serializable {
* 构造
*/
public BeanConverter() {
this(CopyOptions.create().setIgnoreError(true));
this(CopyOptions.of().setIgnoreError(true));
}
/**

View File

@ -247,7 +247,7 @@ public class Dict extends LinkedHashMap<String, Object> implements BasicTypeGett
* @return vo
*/
public <T> T toBeanIgnoreCase(final Class<T> clazz) {
return BeanUtil.toBean(this, clazz, CopyOptions.create().setIgnoreCase(true));
return BeanUtil.toBean(this, clazz, CopyOptions.of().setIgnoreCase(true));
}
/**

View File

@ -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());
}

View File

@ -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<String, Object> 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());
}

View File

@ -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);

View File

@ -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());

View File

@ -12,13 +12,13 @@ public class BeanCopierTest {
public void beanToMapIgnoreNullTest() {
final A a = new A();
HashMap<Object, Object> map = BeanCopier.create(a, new HashMap<>(), CopyOptions.create()).copy();
HashMap<Object, Object> 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<B> copier = BeanCopier.create(a, b, CopyOptions.create().setOverride(false));
final BeanCopier<B> 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<B> copier = BeanCopier.create(a, b, CopyOptions.create());
final BeanCopier<B> copier = BeanCopier.create(a, b, CopyOptions.of());
copier.copy();
Assert.assertEquals("123", b.getValue());

View File

@ -169,7 +169,7 @@ public class JakartaServletUtil {
* @return Bean
*/
public static <T> 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));
}
/**

View File

@ -169,7 +169,7 @@ public class ServletUtil {
* @return Bean
*/
public static <T> 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));
}
/**

View File

@ -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())

View File

@ -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<MutableEntry<String, Object>> filter) {
final CopyOptions copyOptions = InternalJSONUtil.toCopyOptions(jsonObject.getConfig());
copyOptions.setFieldEditor((entry -> filter.accept(entry) ? entry : null));
BeanUtil.beanToMap(bean, jsonObject, copyOptions);
}
}

View File

@ -107,7 +107,7 @@ public final class CsvRow implements List<String> {
* @since 5.3.6
*/
public <T> T toBean(final Class<T> clazz){
return BeanUtil.toBean(getFieldMap(), clazz, CopyOptions.create().setIgnoreError(true));
return BeanUtil.toBean(getFieldMap(), clazz, CopyOptions.of().setIgnoreError(true));
}
/**

View File

@ -42,7 +42,7 @@ public class BeanSheetReader<T> implements SheetReader<List<T>> {
}
final List<T> beanList = new ArrayList<>(mapList.size());
final CopyOptions copyOptions = CopyOptions.create().setIgnoreError(true);
final CopyOptions copyOptions = CopyOptions.of().setIgnoreError(true);
for (final Map<String, Object> map : mapList) {
beanList.add(BeanUtil.toBean(map, this.beanClass, copyOptions));
}

View File

@ -297,7 +297,7 @@ public abstract class AbsSetting implements OptNullBasicTypeFromStringGetter<Str
public boolean containsKey(final String key) {
return null != getByGroup(key, group);
}
}, CopyOptions.create());
}, CopyOptions.of());
}
/**