返回

避开大坑:Java Bean 转 Map 的那些让你出乎意料的骚操作!

后端

一、背景

在实际开发中,我们经常会遇到需要将 Java Bean 转成 Map 的场景。比如:

  • 将 Java Bean 作为参数传递给第三方 API。
  • 将 Java Bean 存储到 NoSQL 数据库中。
  • 将 Java Bean 转换为 JSON 或 XML 格式。

二、那些坑

2.0 测试对象 父类

2.1 JSON 反序列化了类型丢失

2.1.1 问题复现
    JSON json = new JSON();
    String jsonString = json.toJSONString(testObject);
    JSONObject jsonObject = json.parseObject(jsonString);
    System.out.println(jsonObject.get("baseName"));
    System.out.println(jsonObject.get("objName"));

输出结果:

null
null

baseNameobjName 属性都丢失了,因为 JSON 在反序列化时无法区分 TestObjectSubTestObject,导致类型丢失。

2.1.2 解决方案
  • 使用 @JSONField 注解指定 JSON 字段的名称。
  • 使用 @JsonIgnore 注解忽略不需要序列化的属性。
@JSONField(name = "base_name")
private String baseName;

@JSONField(name = "obj_name")
private String objName;

延伸阅读:

2.2 BeanUtils 转换时父类属性丢失

2.2.1 问题复现

    TestObject testObject = new SubTestObject();
    Map<String, Object> map = new HashMap<>();
    BeanUtils.copyProperties(testObject, map);
    System.out.println(map.get("baseName"));
    System.out.println(map.get("objName"));

输出结果:

null
objName

baseName 属性丢失了,因为 BeanUtils 在转换时无法区分 TestObjectSubTestObject,导致父类属性丢失。

2.2.2 解决方案

  • 使用 BeanUtils.copyProperties(Object source, Object target, Class<?>[] ignoreProperties) 方法,忽略不需要转换的属性。
  • 使用 BeanUtils.copyProperties(Object source, Object target, String[] ignoreProperties) 方法,忽略不需要转换的属性。
    BeanUtils.copyProperties(testObject, map, new String[]{"baseName"});

延伸阅读:

2.3 Dozer 转换时父类属性丢失

2.3.1 问题复现

    TestObject testObject = new SubTestObject();
    Map<String, Object> map = new HashMap<>();
    DozerBeanMapper mapper = new DozerBeanMapper();
    mapper.map(testObject, map);
    System.out.println(map.get("baseName"));
    System.out.println(map.get("objName"));

输出结果:

null
objName

baseName 属性丢失了,因为 Dozer 在转换时无法区分 TestObjectSubTestObject,导致父类属性丢失。

2.3.2 解决方案

  • 使用 @Mapping 注解指定需要转换的属性。
  • 使用 @FieldMapping 注解指定需要转换的属性。
@Mapping(value = "baseName", target = "base_name")
private String baseName;

@FieldMapping(value = "objName")
private String objName;

延伸阅读:

2.4 MapStruct 转换时父类属性丢失

2.4.1 问题复现

@Mapper
public interface TestObjectMapper {

    TestObjectDto toDto(TestObject testObject);
}

public class TestObjectDto {

    private String baseName;

    private String objName;
}

public static void main(String[] args) {
    TestObject testObject = new SubTestObject();
    TestObjectMapper mapper = Mappers.getMapper(TestObjectMapper.class);
    TestObjectDto dto = mapper.toDto(testObject);
    System.out.println(dto.getBaseName());
    System.out.println(dto.getObjName());
}

输出结果:

null
objName

baseName 属性丢失了,因为 MapStruct 在转换时无法区分 TestObjectSubTestObject,导致父类属性丢失。

2.4.2 解决方案

  • 使用 @InheritInverseConfiguration 注解继承父类的映射配置。
  • 使用 @InheritConfiguration 注解继承父类的映射配置。
@Mapper(config = InheritInverseConfiguration.class)
public interface TestObjectMapper {

    TestObjectDto toDto(TestObject testObject);
}

延伸阅读:

三、总结

Java Bean 转 Map看似简单,但隐藏着很多容易踩雷的坑。希望本文能够帮助你避开这些坑,轻松转换 Java Bean 与 Map 之间的数据。

最后,需要强调的是,本文仅讨论了 Java Bean 转 Map 的常见坑,还有很多其他的坑需要你去发现和避免。在实际开发中,一定要仔细阅读相关文档,并进行充分的测试。