返回
避开大坑:Java Bean 转 Map 的那些让你出乎意料的骚操作!
后端
2024-01-17 17:05:39
一、背景
在实际开发中,我们经常会遇到需要将 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
baseName
和 objName
属性都丢失了,因为 JSON 在反序列化时无法区分 TestObject
和 SubTestObject
,导致类型丢失。
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 在转换时无法区分 TestObject
和 SubTestObject
,导致父类属性丢失。
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 在转换时无法区分 TestObject
和 SubTestObject
,导致父类属性丢失。
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 在转换时无法区分 TestObject
和 SubTestObject
,导致父类属性丢失。
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 的常见坑,还有很多其他的坑需要你去发现和避免。在实际开发中,一定要仔细阅读相关文档,并进行充分的测试。