From ca16ad9f1d05b85d83a73c6787de7c6f9f5cc07c Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 6 Jul 2024 11:36:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBeanUtil.copyProperties?= =?UTF-8?q?=E4=B8=ADmapToMap=E6=97=B6key=E8=A2=AB=E8=BD=AC=E4=B8=BAString?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/hutool/core/bean/BeanUtil.java | 15 ++++--- .../core/bean/copier/BeanToBeanCopier.java | 5 ++- .../core/bean/copier/BeanToMapCopier.java | 5 ++- .../hutool/core/bean/copier/CopyOptions.java | 19 ++++---- .../core/bean/copier/MapToBeanCopier.java | 7 ++- .../core/bean/copier/MapToMapCopier.java | 2 +- .../copier/ValueProviderToBeanCopier.java | 5 ++- .../hutool/core/text/dfa/WordTree.java | 2 +- .../hutool/core/bean/BeanUtilTest.java | 2 +- .../hutool/core/bean/Issue1687Test.java | 2 +- .../hutool/core/bean/Issue2202Test.java | 2 +- .../hutool/core/bean/Issue3497Test.java | 2 +- .../hutool/core/bean/Issue3645Test.java | 43 +++++++++++++++++++ .../hutool/http/webservice/SoapClient.java | 2 +- .../hutool/json/mapper/JSONObjectMapper.java | 4 +- 15 files changed, 84 insertions(+), 33 deletions(-) create mode 100644 hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue3645Test.java diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/bean/BeanUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/bean/BeanUtil.java index 9c87c3fda..a1a124b80 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/bean/BeanUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/bean/BeanUtil.java @@ -373,12 +373,12 @@ public class BeanUtil { */ public static Map beanToMap(final Object bean, final String... properties) { int mapSize = 16; - UnaryOperator> editor = null; + UnaryOperator> editor = null; if (ArrayUtil.isNotEmpty(properties)) { mapSize = properties.length; final Set propertiesSet = SetUtil.of(properties); editor = entry -> { - final String key = entry.getKey(); + final String key = StrUtil.toStringOrNull(entry.getKey()); entry.setKey(propertiesSet.contains(key) ? key : null); return entry; }; @@ -413,13 +413,14 @@ public class BeanUtil { * @return Map * @since 3.2.3 */ - public static Map beanToMap(final Object bean, final Map targetMap, final boolean isToUnderlineCase, final boolean ignoreNullValue) { + public static Map beanToMap(final Object bean, final Map targetMap, + final boolean isToUnderlineCase, final boolean ignoreNullValue) { if (null == bean) { return null; } return beanToMap(bean, targetMap, ignoreNullValue, entry -> { - final String key = entry.getKey(); + final String key = StrUtil.toStringOrNull(entry.getKey()); entry.setKey(isToUnderlineCase ? StrUtil.toUnderlineCase(key) : key); return entry; }); @@ -442,8 +443,10 @@ public class BeanUtil { * @return Map * @since 4.0.5 */ - public static Map beanToMap(final Object bean, final Map targetMap, - final boolean ignoreNullValue, final UnaryOperator> keyEditor) { + public static Map beanToMap(final Object bean, + final Map targetMap, + final boolean ignoreNullValue, + final UnaryOperator> keyEditor) { if (null == bean) { return null; } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/BeanToBeanCopier.java b/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/BeanToBeanCopier.java index 04e286202..1b703f4fb 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/BeanToBeanCopier.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/BeanToBeanCopier.java @@ -17,6 +17,7 @@ import org.dromara.hutool.core.bean.PropDesc; import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.lang.mutable.MutableEntry; import org.dromara.hutool.core.reflect.TypeUtil; +import org.dromara.hutool.core.text.StrUtil; import java.lang.reflect.Type; import java.util.Map; @@ -73,11 +74,11 @@ public class BeanToBeanCopier extends AbsCopier { } // 编辑键值对 - final MutableEntry entry = copyOptions.editField(sFieldName, sValue); + final MutableEntry entry = copyOptions.editField(sFieldName, sValue); if(null == entry){ return; } - sFieldName = entry.getKey(); + sFieldName = StrUtil.toStringOrNull(entry.getKey()); // 对key做转换,转换后为null的跳过 if (null == sFieldName) { return; diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/BeanToMapCopier.java b/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/BeanToMapCopier.java index 9ad627d6b..3fcb6e059 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/BeanToMapCopier.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/BeanToMapCopier.java @@ -17,6 +17,7 @@ import org.dromara.hutool.core.bean.PropDesc; import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.lang.mutable.MutableEntry; import org.dromara.hutool.core.reflect.TypeUtil; +import org.dromara.hutool.core.text.StrUtil; import java.lang.reflect.Type; import java.util.Map; @@ -72,11 +73,11 @@ public class BeanToMapCopier extends AbsCopier { } // 编辑键值对 - final MutableEntry entry = copyOptions.editField(sFieldName, sValue); + final MutableEntry entry = copyOptions.editField(sFieldName, sValue); if(null == entry){ return; } - sFieldName = entry.getKey(); + sFieldName = StrUtil.toStringOrNull(entry.getKey()); // 对key做转换,转换后为null的跳过 if (null == sFieldName) { return; diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/CopyOptions.java b/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/CopyOptions.java index e5e16d954..d055bc020 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/CopyOptions.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/CopyOptions.java @@ -67,7 +67,7 @@ public class CopyOptions implements Serializable { /** * 字段属性名和属性值编辑器,用于自定义属性转换规则(例如驼峰转下划线等),自定义属性值转换规则(例如null转""等) */ - protected UnaryOperator> fieldEditor; + protected UnaryOperator> fieldEditor; /** * 是否支持transient关键字修饰和@Transient注解,如果支持,被修饰的字段或方法对应的字段将被忽略。 @@ -264,10 +264,11 @@ public class CopyOptions implements Serializable { * @param fieldMapping 拷贝属性的字段映射,用于不同的属性之前拷贝做对应表用 * @return CopyOptions */ - public CopyOptions setFieldMapping(final Map fieldMapping) { + public CopyOptions setFieldMapping(final Map fieldMapping) { return setFieldEditor(entry -> { - final String key = entry.getKey(); - entry.setKey(fieldMapping.getOrDefault(key, key)); + final Object key = entry.getKey(); + final Object keyMapped = fieldMapping.get(key); + entry.setKey(null == keyMapped ? key : keyMapped); return entry; }); } @@ -282,7 +283,7 @@ public class CopyOptions implements Serializable { * @return CopyOptions * @since 5.4.2 */ - public CopyOptions setFieldEditor(final UnaryOperator> editor) { + public CopyOptions setFieldEditor(final UnaryOperator> editor) { this.fieldEditor = editor; return this; } @@ -290,13 +291,13 @@ public class CopyOptions implements Serializable { /** * 编辑字段值 * - * @param fieldName 字段名 - * @param fieldValue 字段值 + * @param key 字段名 + * @param value 字段值 * @return 编辑后的字段值 * @since 5.7.15 */ - protected MutableEntry editField(final String fieldName, final Object fieldValue) { - final MutableEntry entry = new MutableEntry<>(fieldName, fieldValue); + protected MutableEntry editField(final Object key, final Object value) { + final MutableEntry entry = new MutableEntry<>(key, value); return (null != this.fieldEditor) ? this.fieldEditor.apply(entry) : entry; } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/MapToBeanCopier.java b/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/MapToBeanCopier.java index 9ffba6a5a..2174c3eb8 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/MapToBeanCopier.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/MapToBeanCopier.java @@ -19,7 +19,6 @@ import org.dromara.hutool.core.lang.mutable.MutableEntry; import org.dromara.hutool.core.map.CaseInsensitiveMap; import org.dromara.hutool.core.map.MapWrapper; import org.dromara.hutool.core.reflect.TypeUtil; -import org.dromara.hutool.core.text.StrUtil; import java.lang.reflect.Type; import java.util.Map; @@ -76,11 +75,11 @@ public class MapToBeanCopier extends AbsCopier, T> { } // 编辑键值对 - final MutableEntry entry = copyOptions.editField(sKey.toString(), sValue); + final MutableEntry entry = copyOptions.editField(sKey, sValue); if(null == entry){ return; } - final String sFieldName = entry.getKey(); + final Object sFieldName = entry.getKey(); // 对key做转换,转换后为null的跳过 if (null == sFieldName) { return; @@ -88,7 +87,7 @@ public class MapToBeanCopier extends AbsCopier, T> { // 检查目标字段可写性 // 目标字段检查放在键值对编辑之后,因为键可能被编辑修改 - final PropDesc tDesc = this.copyOptions.findPropDesc(targetPropDescMap, sFieldName); + final PropDesc tDesc = this.copyOptions.findPropDesc(targetPropDescMap, sFieldName.toString()); if (null == tDesc || !tDesc.isWritable(this.copyOptions.transientSupport)) { // 字段不可写,跳过之 return; diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/MapToMapCopier.java b/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/MapToMapCopier.java index 59e52f833..219b41b1c 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/MapToMapCopier.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/MapToMapCopier.java @@ -52,7 +52,7 @@ public class MapToMapCopier extends AbsCopier { } // 编辑键值对 - final MutableEntry entry = copyOptions.editField(sKey.toString(), sValue); + final MutableEntry entry = copyOptions.editField(sKey, sValue); if(null == entry){ return; } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/ValueProviderToBeanCopier.java b/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/ValueProviderToBeanCopier.java index 98fef6ed1..96b031a1a 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/ValueProviderToBeanCopier.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/bean/copier/ValueProviderToBeanCopier.java @@ -17,6 +17,7 @@ import org.dromara.hutool.core.bean.PropDesc; import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.lang.mutable.MutableEntry; import org.dromara.hutool.core.reflect.TypeUtil; +import org.dromara.hutool.core.text.StrUtil; import java.lang.reflect.Type; import java.util.Map; @@ -72,11 +73,11 @@ public class ValueProviderToBeanCopier extends AbsCopier entry = copyOptions.editField(tFieldName, null); + final MutableEntry entry = copyOptions.editField(tFieldName, null); if(null == entry){ return; } - tFieldName = entry.getKey(); + tFieldName = StrUtil.toStringOrNull(entry.getKey()); // 对key做转换,转换后为null的跳过 if (null == tFieldName) { return; diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/dfa/WordTree.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/dfa/WordTree.java index 7a46d504e..b88d2c93d 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/text/dfa/WordTree.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/dfa/WordTree.java @@ -374,7 +374,7 @@ public class WordTree extends HashMap { private Iterable innerFlatten(final Entry entry) { final List list = EasyStream.of(entry.getValue().entrySet()).flat(this::innerFlatten).map(v -> entry.getKey() + v).toList(); if (list.isEmpty()) { - return EasyStream.of(entry.getKey().toString()); + return EasyStream.of(StrUtil.toStringOrNull(entry.getKey())); } return list; } diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/bean/BeanUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/bean/BeanUtilTest.java index 43b782a80..a9615e7a7 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/bean/BeanUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/bean/BeanUtilTest.java @@ -879,7 +879,7 @@ public class BeanUtilTest { //setIgnoreNullValue(true). //setIgnoreCase(false). setFieldEditor(entry->{ - entry.setKey(StrUtil.toCamelCase(entry.getKey())); + entry.setKey(StrUtil.toCamelCase(entry.getKey().toString())); return entry; }); diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue1687Test.java b/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue1687Test.java index 09ce5bd4a..4bc3e30f0 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue1687Test.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue1687Test.java @@ -46,7 +46,7 @@ public class Issue1687Test { // 补救别名错位 final CopyOptions copyOptions = CopyOptions.of().setFieldMapping( - MapUtil.builder("depart", "depId").build() + MapUtil.builder((Object)"depart", (Object)"depId").build() ); final SysUser sysUser = BeanUtil.toBean(sysUserFb, SysUser.class, copyOptions); diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue2202Test.java b/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue2202Test.java index a7fe14db5..39471d277 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue2202Test.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue2202Test.java @@ -35,7 +35,7 @@ public class Issue2202Test { headerMap.put("wechatpay-signature", "signature"); final ResponseSignVerifyParams case1 = BeanUtil.toBean(headerMap, ResponseSignVerifyParams.class, CopyOptions.of().setFieldEditor(entry -> { - entry.setKey(NamingCase.toCamelCase(entry.getKey(), '-')); + entry.setKey(NamingCase.toCamelCase(entry.getKey().toString(), '-')); return entry; })); diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue3497Test.java b/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue3497Test.java index ab29a887a..e4d6dd9f8 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue3497Test.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue3497Test.java @@ -14,7 +14,7 @@ public class Issue3497Test { public void setFieldEditorTest() { final Map aB = MapUtil.builder("a_b", "1").build(); final Map bean = BeanUtil.toBean(aB, Map.class, CopyOptions.of().setFieldEditor((entry)->{ - entry.setKey(StrUtil.toCamelCase(entry.getKey())); + entry.setKey(StrUtil.toCamelCase(entry.getKey().toString())); return entry; })); Assertions.assertEquals(bean.toString(), "{aB=1}"); diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue3645Test.java b/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue3645Test.java new file mode 100644 index 000000000..6bfa738a5 --- /dev/null +++ b/hutool-core/src/test/java/org/dromara/hutool/core/bean/Issue3645Test.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.bean; + +import lombok.Data; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class Issue3645Test { + @Test + public void copyPropertiesTest() { + final User p = new User(); + p.setUserId(123L); + + final Map map = new HashMap<>(); + map.put(123L,p); + + final Map m = new HashMap<>(); + BeanUtil.copyProperties(map, m); + final User u = m.get(123L); + assertNotNull(u); + } + + @Data + static class User{ + private Long userId; + } +} diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/webservice/SoapClient.java b/hutool-http/src/main/java/org/dromara/hutool/http/webservice/SoapClient.java index afb5e5fe2..d1e1b5c2a 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/webservice/SoapClient.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/webservice/SoapClient.java @@ -648,7 +648,7 @@ public class SoapClient implements HeaderOperation { Entry entry; for (final Object obj : ((Map) value).entrySet()) { entry = (Entry) obj; - setParam(childEle, entry.getKey().toString(), entry.getValue(), prefix); + setParam(childEle, StrUtil.toStringOrNull(entry.getKey()), entry.getValue(), prefix); } } else { // 单个值 diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/mapper/JSONObjectMapper.java b/hutool-json/src/main/java/org/dromara/hutool/json/mapper/JSONObjectMapper.java index 762de4325..4f9cb4842 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/mapper/JSONObjectMapper.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/mapper/JSONObjectMapper.java @@ -208,7 +208,9 @@ public class JSONObjectMapper { private void mapFromBean(final Object bean, final JSONObject jsonObject) { final CopyOptions copyOptions = InternalJSONUtil.toCopyOptions(jsonObject.config()); if (null != this.predicate) { - copyOptions.setFieldEditor((entry -> this.predicate.test(entry) ? entry : null)); + copyOptions.setFieldEditor((entry -> this.predicate.test( + MutableEntry.of(StrUtil.toStringOrNull(entry.getKey()), entry.getValue())) ? + entry : null)); } BeanUtil.beanToMap(bean, jsonObject, copyOptions); }