From 9ff2d650bb43de6e88f57bafefea874100eb505f Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 25 May 2020 11:36:20 +0800 Subject: [PATCH] add toBean support Map --- CHANGELOG.md | 3 +- .../java/cn/hutool/core/bean/BeanUtil.java | 2 +- .../java/cn/hutool/core/util/ReflectUtil.java | 20 +++++++ .../java/cn/hutool/core/util/StrUtil.java | 56 +++++++++---------- .../cn/hutool/core/bean/BeanUtilTest.java | 16 ++++++ .../core/convert/ConvertToBeanTest.java | 18 ++++-- 6 files changed, 79 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92ffc9924..f383a7b00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -## 5.3.6 (2020-05-19) +## 5.3.6 (2020-05-25) ### 新特性 * 【core 】 NumberConverter Long类型增加日期转换(pr#872@Github) @@ -14,6 +14,7 @@ * 【core 】 ImgUtil增加toBase64DateUri,URLUtil增加getDataUri方法 * 【core 】 IterUtil添加List转Map的工具方法(pr#123@Gitee) * 【core 】 BeanValuePovider转换失败时,返回原数据,而非null +* 【core 】 支持BeanUtil.toBean(object, Map.class)转换(issue#I1I4HC@Gitee) ### Bug修复 * 【core 】 修复SimpleCache死锁问题(issue#I1HOKB@Gitee) 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 c2f3257a7..45e97563d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java @@ -476,7 +476,7 @@ public class BeanUtil { * @since 5.2.4 */ public static T toBean(Object source, Class clazz, CopyOptions options) { - final T target = ReflectUtil.newInstance(clazz); + final T target = ReflectUtil.newInstanceIfPossible(clazz); copyProperties(source, target, options); return target; } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java index 17a5f8c2f..222eb936e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java @@ -13,6 +13,7 @@ import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -769,13 +770,32 @@ public class ReflectUtil { /** * 尝试遍历并调用此类的所有构造方法,直到构造成功并返回 + *

+ * 对于某些特殊的接口,按照其默认实现实例化,例如: + *

+	 *     Map       -》 HashMap
+	 *     Collction -》 ArrayList
+	 *     List      -》 ArrayList
+	 *     Set       -》 HashSet
+	 * 
* * @param 对象类型 * @param beanClass 被构造的类 * @return 构造后的对象 */ + @SuppressWarnings("unchecked") public static T newInstanceIfPossible(Class beanClass) { Assert.notNull(beanClass); + + // 某些特殊接口的实例化按照默认实现进行 + if (beanClass.isAssignableFrom(AbstractMap.class)) { + beanClass = (Class) HashMap.class; + } else if (beanClass.isAssignableFrom(List.class)) { + beanClass = (Class) ArrayList.class; + } else if (beanClass.isAssignableFrom(Set.class)) { + beanClass = (Class) HashSet.class; + } + try { return newInstance(beanClass); } catch (Exception e) { diff --git a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java index 3bcb3bc7f..0d0bc15b1 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java @@ -1741,14 +1741,14 @@ public class StrUtil { * 如果分隔字符串为空串"",则返回空串,如果分隔字符串未找到,返回原字符串,举例如下: * *
-	 * StrUtil.subBefore(null, *)      = null
-	 * StrUtil.subBefore("", *)        = ""
-	 * StrUtil.subBefore("abc", "a")   = ""
-	 * StrUtil.subBefore("abcba", "b") = "a"
-	 * StrUtil.subBefore("abc", "c")   = "ab"
-	 * StrUtil.subBefore("abc", "d")   = "abc"
-	 * StrUtil.subBefore("abc", "")    = ""
-	 * StrUtil.subBefore("abc", null)  = "abc"
+	 * StrUtil.subBefore(null, *, false)      = null
+	 * StrUtil.subBefore("", *, false)        = ""
+	 * StrUtil.subBefore("abc", "a", false)   = ""
+	 * StrUtil.subBefore("abcba", "b", false) = "a"
+	 * StrUtil.subBefore("abc", "c", false)   = "ab"
+	 * StrUtil.subBefore("abc", "d", false)   = "abc"
+	 * StrUtil.subBefore("abc", "", false)    = ""
+	 * StrUtil.subBefore("abc", null, false)  = "abc"
 	 * 
* * @param string 被查找的字符串 @@ -1783,12 +1783,12 @@ public class StrUtil { * 如果分隔字符串未找到,返回原字符串,举例如下: * *
-	 * StrUtil.subBefore(null, *)      = null
-	 * StrUtil.subBefore("", *)        = ""
-	 * StrUtil.subBefore("abc", 'a')   = ""
-	 * StrUtil.subBefore("abcba", 'b') = "a"
-	 * StrUtil.subBefore("abc", 'c')   = "ab"
-	 * StrUtil.subBefore("abc", 'd')   = "abc"
+	 * StrUtil.subBefore(null, *, false)      = null
+	 * StrUtil.subBefore("", *, false)        = ""
+	 * StrUtil.subBefore("abc", 'a', false)   = ""
+	 * StrUtil.subBefore("abcba", 'b', false) = "a"
+	 * StrUtil.subBefore("abc", 'c', false)   = "ab"
+	 * StrUtil.subBefore("abc", 'd', false)   = "abc"
 	 * 
* * @param string 被查找的字符串 @@ -1819,14 +1819,14 @@ public class StrUtil { * 如果分隔字符串为空串(null或""),则返回空串,如果分隔字符串未找到,返回空串,举例如下: * *
-	 * StrUtil.subAfter(null, *)      = null
-	 * StrUtil.subAfter("", *)        = ""
-	 * StrUtil.subAfter(*, null)      = ""
-	 * StrUtil.subAfter("abc", "a")   = "bc"
-	 * StrUtil.subAfter("abcba", "b") = "cba"
-	 * StrUtil.subAfter("abc", "c")   = ""
-	 * StrUtil.subAfter("abc", "d")   = ""
-	 * StrUtil.subAfter("abc", "")    = "abc"
+	 * StrUtil.subAfter(null, *, false)      = null
+	 * StrUtil.subAfter("", *, false)        = ""
+	 * StrUtil.subAfter(*, null, false)      = ""
+	 * StrUtil.subAfter("abc", "a", false)   = "bc"
+	 * StrUtil.subAfter("abcba", "b", false) = "cba"
+	 * StrUtil.subAfter("abc", "c", false)   = ""
+	 * StrUtil.subAfter("abc", "d", false)   = ""
+	 * StrUtil.subAfter("abc", "", false)    = "abc"
 	 * 
* * @param string 被查找的字符串 @@ -1857,12 +1857,12 @@ public class StrUtil { * 如果分隔字符串为空串(null或""),则返回空串,如果分隔字符串未找到,返回空串,举例如下: * *
-	 * StrUtil.subAfter(null, *)      = null
-	 * StrUtil.subAfter("", *)        = ""
-	 * StrUtil.subAfter("abc", 'a')   = "bc"
-	 * StrUtil.subAfter("abcba", 'b') = "cba"
-	 * StrUtil.subAfter("abc", 'c')   = ""
-	 * StrUtil.subAfter("abc", 'd')   = ""
+	 * StrUtil.subAfter(null, *, false)      = null
+	 * StrUtil.subAfter("", *, false)        = ""
+	 * StrUtil.subAfter("abc", 'a', false)   = "bc"
+	 * StrUtil.subAfter("abcba", 'b', false) = "cba"
+	 * StrUtil.subAfter("abc", 'c', false)   = ""
+	 * StrUtil.subAfter("abc", 'd', false)   = ""
 	 * 
* * @param string 被查找的字符串 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 2297e75fe..1ccaa3977 100644 --- a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java @@ -75,6 +75,22 @@ public class BeanUtilTest { Assert.assertEquals(person.getOpenid(), "DFDFSDFWERWER"); } + @Test + public void toBeanTest(){ + SubPerson person = new SubPerson(); + person.setAge(14); + person.setOpenid("11213232"); + person.setName("测试A11"); + person.setSubName("sub名字"); + + final Map map = BeanUtil.toBean(person, Map.class); + Assert.assertEquals("测试A11", map.get("name")); + Assert.assertEquals(14, map.get("age")); + Assert.assertEquals("11213232", map.get("openid")); + // static属性应被忽略 + Assert.assertFalse(map.containsKey("SUBNAME")); + } + @Test public void mapToBeanIgnoreCaseTest() { HashMap map = CollUtil.newHashMap(); diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToBeanTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToBeanTest.java index b9ed303d9..166dc6dde 100644 --- a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToBeanTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToBeanTest.java @@ -1,15 +1,15 @@ package cn.hutool.core.convert; +import cn.hutool.core.bean.BeanUtilTest.SubPerson; +import cn.hutool.core.lang.Console; +import cn.hutool.core.lang.TypeReference; +import org.junit.Assert; +import org.junit.Test; + import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; -import cn.hutool.core.lang.Console; -import org.junit.Assert; -import org.junit.Test; - -import cn.hutool.core.bean.BeanUtilTest.SubPerson; - /** * 类型转换工具单元测试
* 转换为数组 @@ -45,6 +45,12 @@ public class ConvertToBeanTest { Assert.assertEquals("测试A11", map.get("name")); Assert.assertEquals("14", map.get("age")); Assert.assertEquals("11213232", map.get("openid")); + + final LinkedHashMap map2 = Convert.convert( + new TypeReference>() {}, person); + Assert.assertEquals("测试A11", map2.get("name")); + Assert.assertEquals("14", map2.get("age")); + Assert.assertEquals("11213232", map2.get("openid")); } @Test