zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Dozer对象映射框架Map到JSONString映射问题排查

Map对象框架映射 排查 问题
2023-09-14 09:04:39 时间
## 引言 Dozer是一个优秀的对象映射的框架,可以帮助程序员减少大量的对象之间映射的get/set代码,在ATA上有好几篇文章介绍了dozer的使用: [dozer开发手册](http://www.atatech.org/articles/31144) [使用Dozer帮你提高开发效率(解决繁琐的DO转BO、TO转BO问题)](http://www.atatech.org/article

Dozer是一个优秀的对象映射的框架,可以帮助程序员减少大量的对象之间映射的get/set代码,在ATA上有好几篇文章介绍了dozer的使用:
dozer开发手册
使用Dozer帮你提高开发效率(解决繁琐的DO转BO、TO转BO问题) 有兴趣的同学,可以去看下基本的使用。

我在开发后台系统中,经常会遇到从前台提交的对象,转为后台的服务模型对象做操作,通过dozer工具,灵活的配置就可以轻易的解决。我需要将将一个对象的Map对象转为json的字符串,按照dozer的文档需要编写自定义的Convertor来进行处理(这里面针对字段的转换,,dozer支持类级别,字段级别的Convertor. ),但测试却发现了一些问题。具体请看例子:

源对象

 public class SourceA{

 private Map String,Object field;

 //省略get/set

 public class SourceB{

 private String field;

 //省略get/set

 //dozerMapper配置

 ?xml version="1.0" encoding="UTF-8"? 

 mappings xmlns="http://dozer.sourceforge.net"

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 xsi:schemaLocation="http://dozer.sourceforge.net

 http://dozer.sourceforge.net/schema/beanmapping.xsd" 

 mapping type="bi-directional" 

 class-a com.alibaba.xxx.SourceA /class-a 

 class-b com.alibaba.xxx.SourceB /class-b 

 field custom-converter="com.alibaba.xxx.JsonConverter" 

 a field /a 

 b field /b 

 /field 

 /mapping 

 /mappings 

//自定义的Convertor

public class JsonConverter extends DozerConverter Map,String {

 public JsonConverter(){

 super(Map.class, String.class);

 @Override

 public String convertTo(Map source, String destination) {

 if (source == null) {

 return null;

 return JSON.toJSONString(source);

 @Override

 public Map convertFrom(String source, Map destination) {

 if (source == null) {

 return null;

 return JSON.parseObject(source);

 //单元测试:

 @RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = { "classpath:dozer_test/test.xml" })

public class DozerBugTest {

 @Resource

 DozerBeanMapper dozerBeanMapper;

 @Test

 public void test_mapper(){

 SourceA sa = new SourceA();

 Map String,Object map = Maps.newHashMap();

 map.put("losemoney", "losemoney");

 clueInfo.setField(map);

 SourceB sourceB = new SourceB();

 dozerBeanMapper.map(sa, sourceB);

 assertNotNull(sourceB.getField());

}

从结果上,我是期望传入的Map对象自动可以转为JSON的字符串进行处理,但是跑了单元测试执行的结果是不通过。

我在自定义的转换器JsonConverter类的convertTo方法中加了断点,发现了传入的源对象是一个空值:
screenshot
为什么明明有map对象设置,到自定义转换器哪里就为空了。于是从dozer的map方法开始debug:

实际是调用了MappingProcessor做映射处理,
screenshot 获取每个字段的值:screenshot 从断点显示的值看,这里取到的就是null了。 问题就应该出在 srcFieldValue = fieldMapping.getSrcFieldValue(srcObj); FieldMap有多个对象实现类,screenshot,在这里需要查看MapFieldMap获取对象。
screenshot,默认设置Map和字段做映射的时候,会将Map作为对象,调用get方法,以配置的字段名作为key获取值,在这个场景就是Map.get("field")取值,所以取到的为空。 解决方案其实很简单,更改配置映射文件加上java.util.HashMap
 ?xml version="1.0" encoding="UTF-8"? 

 mappings xmlns="http://dozer.sourceforge.net"

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 xsi:schemaLocation="http://dozer.sourceforge.net

 http://dozer.sourceforge.net/schema/beanmapping.xsd" 

 mapping type="bi-directional" 

 class-a com.alibaba.xxx.SourceA /class-a 

 class-b com.alibaba.xxx.SourceB /class-b 

 field custom-converter="com.alibaba.xxx.JsonConverter" 

 a field /a 

 b field /b 

 a-hint java.util.HashMap /a-hint 

 /field 

 /mapping 

 /mappings 
重新执行后:
screenshot

由于getSrcHintContainer() 不为空,会执行到标红的逻辑,即直接从对象中获取Map的字段作为值返回,
screenshot


我学会了,封装自己得专属映射Map 映射是高层的数据结构,高层的数据结构还有栈和队列,这种数据结构更像是定义好了这种数据结构的相应的使用接口。 有了这些使用的接口包括这些数据结构本身所维持的一些性质,就可以非常容易的把它们放入一些具体的应用中,但是底层实现可以是多种多样的。 比如栈和队列的底层实现即可以是动态数组也可以是链表,映射 Map 也是类似这样的数据结构。
Hibernate【映射】知识要点 前面的我们使用的是一个表的操作,但我们实际的开发中不可能只使用一个表的...因此,本博文主要讲解关联映射 需求分析:当用户购买商品,用户可能有多个地址。 我们一般如下图一样设计数据库表,一般我们不会在User表设计多个列来保存地址的。