Java Bean 转 Map 的巨坑,注意了!!!

打印 上一主题 下一主题

主题 880|帖子 880|积分 2644

作者:明明如月学长
链接:https://juejin.cn/post/7118073840999071751
一、背景

有些业务场景下需要将 Java Bean 转成 Map 再使用。
本以为很简单场景,但是坑很多。
二、那些坑

2.0 测试对象
  1. import lombok.Data;
  2. import java.util.Date;
  3. @Data
  4. public class MockObject extends  MockParent{
  5.     private Integer aInteger;
  6.     private Long aLong;
  7.     private Double aDouble;
  8.     private Date aDate;
  9. }
复制代码
父类
  1. import lombok.Data;
  2. @Data
  3. public class MockParent {
  4.     private Long parent;
  5. }
复制代码
2.1 JSON 反序列化了类型丢失

2.1.1 问题复现

将 Java Bean 转 Map 最常见的手段就是使用  JSON 框架,如 fastjson 、 gson、jackson 等。 但使用 JSON 将 Java Bean 转 Map 会导致部分数据类型丢失。 如使用 fastjson ,当属性为 Long 类型但数字小于 Integer 最大值时,反序列成 Map 之后,将变为  Integer 类型。
maven 依赖:
  1. <dependency>
  2.     <groupId>com.alibaba</groupId>
  3.     <artifactId>fastjson</artifactId>
  4.     <version>2.0.8</version>
  5. </dependency>
复制代码
示例代码:
  1. import com.alibaba.fastjson.JSON;
  2. import com.alibaba.fastjson.TypeReference;
  3. import java.util.Date;
  4. import java.util.Map;
  5. public class JsonDemo {
  6.     public static void main(String[] args) {
  7.         MockObject mockObject = new MockObject();
  8.         mockObject.setAInteger(1);
  9.         mockObject.setALong(2L);
  10.         mockObject.setADate(new Date());
  11.         mockObject.setADouble(3.4D);
  12.         mockObject.setParent(3L);
  13.        String json = JSON.toJSONString(mockObject);
  14.         Map<String,Object> map =  JSON.parseObject(json, new TypeReference<Map<String,Object>>(){});
  15.         System.out.println(map);
  16.     }
  17. }
复制代码
结果打印:
{"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 版本:
  1. <dependency>
  2.     <groupId>commons-beanutils</groupId>
  3.     <artifactId>commons-beanutils</artifactId>
  4.     <version>1.9.4</version>
  5. </dependency>
复制代码
代码示例:
  1. import org.apache.commons.beanutils.BeanMap;
  2. import third.fastjson.MockObject;
  3. import java.util.Date;
  4. public class BeanUtilsDemo {
  5.     public static void main(String[] args) {
  6.         MockObject mockObject = new MockObject();
  7.         mockObject.setAInteger(1);
  8.         mockObject.setALong(2L);
  9.         mockObject.setADate(new Date());
  10.         mockObject.setADouble(3.4D);
  11.         mockObject.setParent(3L);
  12.         BeanMap beanMap = new BeanMap(mockObject);
  13.         System.out.println(beanMap);
  14.     }
  15. }
复制代码
调试截图:
存在和 cglib 一样的问题,虽然类型没问题但是属性名还是不对。
原因分析:
  1. /**
  2. * Constructs a new BeanMap that operates on the
  3. * specified bean.  If the given bean is null, then
  4. * this map will be empty.
  5. *
  6. * @param bean  the bean for this map to operate on
  7. */
  8. public BeanMap(final Object bean) {
  9.     this.bean = bean;
  10.     initialise();
  11. }
复制代码
关键代码:
[code]private void initialise() {    if(getBean() == null) {        return;    }    final Class

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

刘俊凯

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表