作者:明明如月学长
链接:https://juejin.cn/post/7118073840999071751
一、背景
有些业务场景下需要将 Java Bean 转成 Map 再使用。
本以为很简单场景,但是坑很多。
二、那些坑
2.0 测试对象
- import lombok.Data;
- import java.util.Date;
- @Data
- public class MockObject extends MockParent{
- private Integer aInteger;
- private Long aLong;
- private Double aDouble;
- private Date aDate;
- }
复制代码 父类- import lombok.Data;
- @Data
- public class MockParent {
- private Long parent;
- }
复制代码 2.1 JSON 反序列化了类型丢失
2.1.1 问题复现
将 Java Bean 转 Map 最常见的手段就是使用 JSON 框架,如 fastjson 、 gson、jackson 等。 但使用 JSON 将 Java Bean 转 Map 会导致部分数据类型丢失。 如使用 fastjson ,当属性为 Long 类型但数字小于 Integer 最大值时,反序列成 Map 之后,将变为 Integer 类型。
maven 依赖:- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>fastjson</artifactId>
- <version>2.0.8</version>
- </dependency>
复制代码 示例代码:- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.TypeReference;
- import java.util.Date;
- import java.util.Map;
- public class JsonDemo {
- public static void main(String[] args) {
- MockObject mockObject = new MockObject();
- mockObject.setAInteger(1);
- mockObject.setALong(2L);
- mockObject.setADate(new Date());
- mockObject.setADouble(3.4D);
- mockObject.setParent(3L);
- String json = JSON.toJSONString(mockObject);
- Map<String,Object> map = JSON.parseObject(json, new TypeReference<Map<String,Object>>(){});
- System.out.println(map);
- }
- }
复制代码 结果打印:
{"parent":3,"ADouble":3.4,"ALong":2,"AInteger":1,"ADate":1657299916477}
调试截图:
通过 Java Visualizer 插件进行可视化查看:

2.2.2 问题描述
存在两个问题 (1) 通过 fastjson 将 Java Bean 转为 Map ,类型会发生转变。 如 Long 变成 Integer ,Date 变成 Long, Double 变成 Decimal 类型等。 (2)在某些场景下,Map 的 key 并非和属性名完全对应,像是通过 get set 方法“推断”出来的属性名。
2.2 BeanMap 转换属性名错误
2.2.1 commons-beanutils 的 BeanMap
maven 版本:- <dependency>
- <groupId>commons-beanutils</groupId>
- <artifactId>commons-beanutils</artifactId>
- <version>1.9.4</version>
- </dependency>
复制代码 代码示例:- import org.apache.commons.beanutils.BeanMap;
- import third.fastjson.MockObject;
- import java.util.Date;
- public class BeanUtilsDemo {
- public static void main(String[] args) {
- MockObject mockObject = new MockObject();
- mockObject.setAInteger(1);
- mockObject.setALong(2L);
- mockObject.setADate(new Date());
- mockObject.setADouble(3.4D);
- mockObject.setParent(3L);
- BeanMap beanMap = new BeanMap(mockObject);
- System.out.println(beanMap);
- }
- }
复制代码 调试截图:
存在和 cglib 一样的问题,虽然类型没问题但是属性名还是不对。
原因分析:- /**
- * Constructs a new BeanMap that operates on the
- * specified bean. If the given bean is null, then
- * this map will be empty.
- *
- * @param bean the bean for this map to operate on
- */
- public BeanMap(final Object bean) {
- this.bean = bean;
- initialise();
- }
复制代码 关键代码:
[code]private void initialise() { if(getBean() == null) { return; } final Class |