修复 BeanUtil#copyProperties 源对象与目标对象都是 Map 时设置忽略属性无效问题

This commit is contained in:
Looly 2022-11-08 20:20:50 +08:00
parent 4fdc443a4e
commit a293fd5510
8 changed files with 40 additions and 28 deletions

View File

@ -21,6 +21,7 @@
* 【core 】 修复StrUtil.subWithLength负数问题issue#I5YN49@Gitee
* 【core 】 修复DefaultTrustManager空指针问题issue#2716@Github
* 【core 】 修复时间轮添加任务线程安全问题pr#2712@Github
* 【core 】 修复 BeanUtil#copyProperties 源对象与目标对象都是 Map 时设置忽略属性无效问题pr#2698@Github
-------------------------------------------------------------------------------------------------------------
# 5.8.9 (2022-10-22)

View File

@ -59,6 +59,11 @@ public class BeanToBeanCopier<S, T> extends AbsCopier<S, T> {
return;
}
// 忽略不需要拷贝的 key,
if (false == copyOptions.testKeyFilter(sFieldName)) {
return;
}
// 检查目标字段可写性
final PropDesc tDesc = targetPropDescMap.get(sFieldName);
if (null == tDesc || false == tDesc.isWritable(this.copyOptions.transientSupport)) {

View File

@ -57,6 +57,11 @@ public class BeanToMapCopier extends AbsCopier<Object, Map> {
return;
}
// 忽略不需要拷贝的 key,
if (false == copyOptions.testKeyFilter(sFieldName)) {
return;
}
// 检查源对象属性是否过滤属性
Object sValue = sDesc.getValue(this.source);
if (false == copyOptions.testPropertyFilter(sDesc.getField(), sValue)) {

View File

@ -1,5 +1,6 @@
package cn.hutool.core.bean.copier;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.convert.TypeConverter;
import cn.hutool.core.lang.Editor;
@ -12,8 +13,6 @@ import cn.hutool.core.util.ReflectUtil;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
@ -74,7 +73,7 @@ public class CopyOptions implements Serializable {
/**
* 源对象和目标对象都是 {@code Map} , 需要忽略的源对象 {@code Map} key
*/
private Set<Object> ignoreKeySet;
private Set<String> ignoreKeySet;
/**
* 自定义类型转换器默认使用全局万能转换器转换
@ -188,8 +187,8 @@ public class CopyOptions implements Serializable {
* @return CopyOptions
*/
public CopyOptions setIgnoreProperties(String... ignoreProperties) {
this.setIgnoreKeySet(ignoreProperties);
return setPropertiesFilter((field, o) -> false == ArrayUtil.contains(ignoreProperties, field.getName()));
this.ignoreKeySet = CollUtil.newHashSet(ignoreProperties);
return this;
}
/**
@ -203,8 +202,8 @@ public class CopyOptions implements Serializable {
*/
@SuppressWarnings("unchecked")
public <P, R> CopyOptions setIgnoreProperties(Func1<P, R>... funcs) {
final Set<String> ignoreProperties = ArrayUtil.mapToSet(funcs, LambdaUtil::getFieldName);
return setPropertiesFilter((field, o) -> false == ignoreProperties.contains(field.getName()));
this.ignoreKeySet = ArrayUtil.mapToSet(funcs, LambdaUtil::getFieldName);
return this;
}
/**
@ -228,16 +227,6 @@ public class CopyOptions implements Serializable {
return setIgnoreError(true);
}
/**
* 设置忽略源 {@link Map} key set
* @param ignoreProperties 忽略的key
* @return CopyOptions
*/
public CopyOptions setIgnoreKeySet(String... ignoreProperties) {
this.ignoreKeySet = new HashSet<>(Arrays.asList(ignoreProperties));
return this;
}
/**
* 设置是否忽略字段的大小写
*
@ -388,7 +377,7 @@ public class CopyOptions implements Serializable {
* @param key {@link Map} key
* @return 是否保留
*/
protected boolean testMapKeyFilter(Object key) {
return this.ignoreKeySet.contains(key);
protected boolean testKeyFilter(Object key) {
return CollUtil.isEmpty(this.ignoreKeySet) || false == this.ignoreKeySet.contains(key);
}
}

View File

@ -67,6 +67,11 @@ public class MapToBeanCopier<T> extends AbsCopier<Map<?, ?>, T> {
return;
}
// 忽略不需要拷贝的 key,
if (false == copyOptions.testKeyFilter(sKeyStr)) {
return;
}
// 检查目标字段可写性
final PropDesc tDesc = findPropDesc(targetPropDescMap, sKeyStr);
if (null == tDesc || false == tDesc.isWritable(this.copyOptions.transientSupport)) {

View File

@ -48,18 +48,17 @@ public class MapToMapCopier extends AbsCopier<Map, Map> {
return;
}
// 忽略不需要拷贝的 key,
if (false == copyOptions.testKeyFilter(sKeyStr)) {
return;
}
final Object targetValue = target.get(sKeyStr);
// 非覆盖模式下如果目标值存在则跳过
if (false == copyOptions.override && null != targetValue) {
return;
}
// 忽略不需要拷贝的 key,
if (true == copyOptions.testMapKeyFilter(sKey)) {
return;
}
// 获取目标值真实类型并转换源值
final Type[] typeArguments = TypeUtil.getTypeArguments(this.targetType);
if (null != typeArguments) {

View File

@ -60,6 +60,11 @@ public class ValueProviderToBeanCopier<T> extends AbsCopier<ValueProvider<String
return;
}
// 忽略不需要拷贝的 key,
if (false == copyOptions.testKeyFilter(tFieldName)) {
return;
}
// 检查目标字段可写性
if (null == tDesc || false == tDesc.isWritable(this.copyOptions.transientSupport)) {
// 字段不可写跳过之

View File

@ -1,6 +1,7 @@
package cn.hutool.core.bean;
import org.junit.Assert;
import org.junit.Test;
import java.util.HashMap;
@ -13,12 +14,14 @@ public class Issue2697Test {
@Test
public void mapToMapTest(){
Map<String, String> mapA = new HashMap<>(16);
final Map<String, String> mapA = new HashMap<>(16);
mapA.put("12", "21");
mapA.put("121", "21");
mapA.put("122", "21");
Map<String, String> mapB = new HashMap<>(16);
final Map<String, String> mapB = new HashMap<>(16);
BeanUtil.copyProperties(mapA, mapB, "12");
System.out.println(mapB);
Assert.assertEquals(2, mapB.size());
Assert.assertFalse(mapB.containsKey("12"));
}
}