mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-24 18:04:54 +08:00
fix
This commit is contained in:
parent
084870261f
commit
9b9b35ffc2
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
// 目标赋值
|
||||
|
@ -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}不保留
|
||||
*
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -38,7 +38,7 @@ public class BeanConverter implements Converter, Serializable {
|
||||
* 构造
|
||||
*/
|
||||
public BeanConverter() {
|
||||
this(CopyOptions.create().setIgnoreError(true));
|
||||
this(CopyOptions.of().setIgnoreError(true));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
@ -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());
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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())
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user