add toBean support Map

This commit is contained in:
Looly
2020-05-25 11:36:20 +08:00
parent b9e468d6c7
commit 9ff2d650bb
6 changed files with 79 additions and 36 deletions

View File

@@ -3,7 +3,7 @@
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
## 5.3.6 (2020-05-19) ## 5.3.6 (2020-05-25)
### 新特性 ### 新特性
* 【core 】 NumberConverter Long类型增加日期转换pr#872@Github * 【core 】 NumberConverter Long类型增加日期转换pr#872@Github
@@ -14,6 +14,7 @@
* 【core 】 ImgUtil增加toBase64DateUriURLUtil增加getDataUri方法 * 【core 】 ImgUtil增加toBase64DateUriURLUtil增加getDataUri方法
* 【core 】 IterUtil添加List转Map的工具方法pr#123@Gitee * 【core 】 IterUtil添加List转Map的工具方法pr#123@Gitee
* 【core 】 BeanValuePovider转换失败时返回原数据而非null * 【core 】 BeanValuePovider转换失败时返回原数据而非null
* 【core 】 支持BeanUtil.toBean(object, Map.class)转换issue#I1I4HC@Gitee
### Bug修复 ### Bug修复
* 【core 】 修复SimpleCache死锁问题issue#I1HOKB@Gitee * 【core 】 修复SimpleCache死锁问题issue#I1HOKB@Gitee

View File

@@ -476,7 +476,7 @@ public class BeanUtil {
* @since 5.2.4 * @since 5.2.4
*/ */
public static <T> T toBean(Object source, Class<T> clazz, CopyOptions options) { public static <T> T toBean(Object source, Class<T> clazz, CopyOptions options) {
final T target = ReflectUtil.newInstance(clazz); final T target = ReflectUtil.newInstanceIfPossible(clazz);
copyProperties(source, target, options); copyProperties(source, target, options);
return target; return target;
} }

View File

@@ -13,6 +13,7 @@ import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.AbstractMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@@ -769,13 +770,32 @@ public class ReflectUtil {
/** /**
* 尝试遍历并调用此类的所有构造方法,直到构造成功并返回 * 尝试遍历并调用此类的所有构造方法,直到构造成功并返回
* <p>
* 对于某些特殊的接口,按照其默认实现实例化,例如:
* <pre>
* Map -》 HashMap
* Collction -》 ArrayList
* List -》 ArrayList
* Set -》 HashSet
* </pre>
* *
* @param <T> 对象类型 * @param <T> 对象类型
* @param beanClass 被构造的类 * @param beanClass 被构造的类
* @return 构造后的对象 * @return 构造后的对象
*/ */
@SuppressWarnings("unchecked")
public static <T> T newInstanceIfPossible(Class<T> beanClass) { public static <T> T newInstanceIfPossible(Class<T> beanClass) {
Assert.notNull(beanClass); Assert.notNull(beanClass);
// 某些特殊接口的实例化按照默认实现进行
if (beanClass.isAssignableFrom(AbstractMap.class)) {
beanClass = (Class<T>) HashMap.class;
} else if (beanClass.isAssignableFrom(List.class)) {
beanClass = (Class<T>) ArrayList.class;
} else if (beanClass.isAssignableFrom(Set.class)) {
beanClass = (Class<T>) HashSet.class;
}
try { try {
return newInstance(beanClass); return newInstance(beanClass);
} catch (Exception e) { } catch (Exception e) {

View File

@@ -1741,14 +1741,14 @@ public class StrUtil {
* 如果分隔字符串为空串"",则返回空串,如果分隔字符串未找到,返回原字符串,举例如下: * 如果分隔字符串为空串"",则返回空串,如果分隔字符串未找到,返回原字符串,举例如下:
* *
* <pre> * <pre>
* StrUtil.subBefore(null, *) = null * StrUtil.subBefore(null, *, false) = null
* StrUtil.subBefore("", *) = "" * StrUtil.subBefore("", *, false) = ""
* StrUtil.subBefore("abc", "a") = "" * StrUtil.subBefore("abc", "a", false) = ""
* StrUtil.subBefore("abcba", "b") = "a" * StrUtil.subBefore("abcba", "b", false) = "a"
* StrUtil.subBefore("abc", "c") = "ab" * StrUtil.subBefore("abc", "c", false) = "ab"
* StrUtil.subBefore("abc", "d") = "abc" * StrUtil.subBefore("abc", "d", false) = "abc"
* StrUtil.subBefore("abc", "") = "" * StrUtil.subBefore("abc", "", false) = ""
* StrUtil.subBefore("abc", null) = "abc" * StrUtil.subBefore("abc", null, false) = "abc"
* </pre> * </pre>
* *
* @param string 被查找的字符串 * @param string 被查找的字符串
@@ -1783,12 +1783,12 @@ public class StrUtil {
* 如果分隔字符串未找到,返回原字符串,举例如下: * 如果分隔字符串未找到,返回原字符串,举例如下:
* *
* <pre> * <pre>
* StrUtil.subBefore(null, *) = null * StrUtil.subBefore(null, *, false) = null
* StrUtil.subBefore("", *) = "" * StrUtil.subBefore("", *, false) = ""
* StrUtil.subBefore("abc", 'a') = "" * StrUtil.subBefore("abc", 'a', false) = ""
* StrUtil.subBefore("abcba", 'b') = "a" * StrUtil.subBefore("abcba", 'b', false) = "a"
* StrUtil.subBefore("abc", 'c') = "ab" * StrUtil.subBefore("abc", 'c', false) = "ab"
* StrUtil.subBefore("abc", 'd') = "abc" * StrUtil.subBefore("abc", 'd', false) = "abc"
* </pre> * </pre>
* *
* @param string 被查找的字符串 * @param string 被查找的字符串
@@ -1819,14 +1819,14 @@ public class StrUtil {
* 如果分隔字符串为空串null或""),则返回空串,如果分隔字符串未找到,返回空串,举例如下: * 如果分隔字符串为空串null或""),则返回空串,如果分隔字符串未找到,返回空串,举例如下:
* *
* <pre> * <pre>
* StrUtil.subAfter(null, *) = null * StrUtil.subAfter(null, *, false) = null
* StrUtil.subAfter("", *) = "" * StrUtil.subAfter("", *, false) = ""
* StrUtil.subAfter(*, null) = "" * StrUtil.subAfter(*, null, false) = ""
* StrUtil.subAfter("abc", "a") = "bc" * StrUtil.subAfter("abc", "a", false) = "bc"
* StrUtil.subAfter("abcba", "b") = "cba" * StrUtil.subAfter("abcba", "b", false) = "cba"
* StrUtil.subAfter("abc", "c") = "" * StrUtil.subAfter("abc", "c", false) = ""
* StrUtil.subAfter("abc", "d") = "" * StrUtil.subAfter("abc", "d", false) = ""
* StrUtil.subAfter("abc", "") = "abc" * StrUtil.subAfter("abc", "", false) = "abc"
* </pre> * </pre>
* *
* @param string 被查找的字符串 * @param string 被查找的字符串
@@ -1857,12 +1857,12 @@ public class StrUtil {
* 如果分隔字符串为空串null或""),则返回空串,如果分隔字符串未找到,返回空串,举例如下: * 如果分隔字符串为空串null或""),则返回空串,如果分隔字符串未找到,返回空串,举例如下:
* *
* <pre> * <pre>
* StrUtil.subAfter(null, *) = null * StrUtil.subAfter(null, *, false) = null
* StrUtil.subAfter("", *) = "" * StrUtil.subAfter("", *, false) = ""
* StrUtil.subAfter("abc", 'a') = "bc" * StrUtil.subAfter("abc", 'a', false) = "bc"
* StrUtil.subAfter("abcba", 'b') = "cba" * StrUtil.subAfter("abcba", 'b', false) = "cba"
* StrUtil.subAfter("abc", 'c') = "" * StrUtil.subAfter("abc", 'c', false) = ""
* StrUtil.subAfter("abc", 'd') = "" * StrUtil.subAfter("abc", 'd', false) = ""
* </pre> * </pre>
* *
* @param string 被查找的字符串 * @param string 被查找的字符串

View File

@@ -75,6 +75,22 @@ public class BeanUtilTest {
Assert.assertEquals(person.getOpenid(), "DFDFSDFWERWER"); 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 @Test
public void mapToBeanIgnoreCaseTest() { public void mapToBeanIgnoreCaseTest() {
HashMap<String, Object> map = CollUtil.newHashMap(); HashMap<String, Object> map = CollUtil.newHashMap();

View File

@@ -1,15 +1,15 @@
package cn.hutool.core.convert; 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.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; 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;
/** /**
* 类型转换工具单元测试<br> * 类型转换工具单元测试<br>
* 转换为数组 * 转换为数组
@@ -45,6 +45,12 @@ public class ConvertToBeanTest {
Assert.assertEquals("测试A11", map.get("name")); Assert.assertEquals("测试A11", map.get("name"));
Assert.assertEquals("14", map.get("age")); Assert.assertEquals("14", map.get("age"));
Assert.assertEquals("11213232", map.get("openid")); Assert.assertEquals("11213232", map.get("openid"));
final LinkedHashMap<String, String> map2 = Convert.convert(
new TypeReference<LinkedHashMap<String, String>>() {}, person);
Assert.assertEquals("测试A11", map2.get("name"));
Assert.assertEquals("14", map2.get("age"));
Assert.assertEquals("11213232", map2.get("openid"));
} }
@Test @Test