使用 Dozer 的自定义转换器将对象列表映射到另一个列表

Posted

技术标签:

【中文标题】使用 Dozer 的自定义转换器将对象列表映射到另一个列表【英文标题】:Map a list of object to another list using Dozer's custom converters 【发布时间】:2015-03-13 13:40:49 【问题描述】:

我要做的是使用 Dozer 将实体列表映射到它们的字符串 id 列表(或多或少)。

显然,它意味着自定义转换器。我的第一个想法是做一个从 MyEntity 到 String 的转换器,然后对 Dozer 说“使用这个转换器映射这个集合的每个对象”。但我不知道该怎么做。

所以我的第二个想法是让转换器直接从实体列表到字符串列表。我对这个想法的问题是我正在努力解决一些荒谬的事情,即在构造函数中获取我的列表类型,如下所示(根本不起作用):

public MyEntityListConverter() 
    super(List<MyEntity>.class, List<String>.class);

我不知道如何在不声明任何内容的情况下在单行中传递实例化列表的类。

所以如果有人知道:

如何为推土机指定要在集合映射中使用的对象转换器 如何获取实例化列表类型 尝试第三种/更好的解决方案

【问题讨论】:

【参考方案1】:

由于泛型类型,您尝试的方式是不可能的。如果是,Dozer 无法在运行时检测类型。

第一个解决方案List&lt;&gt;

您的转换器:

public class MyEntityToStringConverter extends DozerConverter<MyEntity, String> 
    // TODO constructor + impl

您的映射:

mapping(MyEntityA.class, MyEntityB.class)
.fields("myEntityList", "myStringList",
    hintA(MyEntity.class),
    hintB(String.class));

mapping(MyEntity.class, String.class)
.fields(this_(), this_(), customConverter(MyEntityToStringConverter.class));

第二个解决方案与列表包装

您可以尝试创建自定义类来扩展列表 impl。

public class MyEntityList extends ArrayList<MyEntity> 



public class MyStringList extends ArrayList<String> 


更改您要映射的父类中的字段。

您的转换器:

public class MyEntityToStringConverter extends DozerConverter<MyEntityList, MyStringList> 
    // TODO constructor + impl

您的映射:

mapping(MyEntityA.class, MyEntityB.class)
.fields("myEntityList", "myStringList", customConverter(MyEntityToStringConverter.class));

【讨论】:

谢谢伙计,我无法尝试,我不再参与这个项目,但我很确定它会起作用,所以我接受了答案。 @LudovicGuillaume 我测试了 解决方案 1 的一半,我可以确定它工作正常。但是我在使用this 进行字段映射时发现了一个问题——我必须通过传入的参数而不是返回对象来返回值。但我无法更改String 的值,因为它总是按值传递。我错过了什么吗? 其实我不明白你有什么问题。解决方案1的第二个映射意味着MyEntity可以通过MyEntityToStringConverter映射到String。请注意,它不是this,而是this_()。转换器的方法应该是MyEntity convert*(String)String convert*(MyEntity) 请问是什么版本的推土机?目前在 6.1.0 和 6.2.0 上,此解决方案为我提供了实体中 toString 的值。通过查看 Dozer 代码,如果源或目标中的任何一个是基元,则 MappingProcessor 中的 mapOrRecurseObject 方法使用 PrimitiveOrWrapperConverter。此转换器假定两个参数都是原语并遵守基本映射,即不支持自定义映射。【参考方案2】:

另一种选择是

super((Class<List<MyEntity>>) (Class<?>) List.class,(Class<List<String>>) (Class<?>) List.class);

【讨论】:

首先,这行得通,所以我赞成。但值得一提的是这个解决方案有一个警告——因为泛型类型在运行时被删除,DozerConverter 实际上无法区分sourcedestination,因为两者都有List.class 的数据类型。因此它总是调用convertFrom() 方法,这使得转换器以一种方式工作,而不是另一种。【参考方案3】:

我非常倾向于@Ludovic 解决方案,但我的comment up there 中可能会提到一个问题。

但对我来说稍作调整 - 在“配置”而不是字段级别注册自定义转换器。我正在使用 XML 配置,但它应该与编码配置一起使用:

<configuration>
  <custom-converters>
    <converter type="f.q.c.n.MyEntityToStringConverter">
      <class-a>java.lang.String</class-a>
      <class-b>f.q.c.n.MyEntity</class-b>
    </converter>
  </custom-converters>
</configuration>

【讨论】:

以上是关于使用 Dozer 的自定义转换器将对象列表映射到另一个列表的主要内容,如果未能解决你的问题,请参考以下文章

四品达通用权限系统__pd-tools-dozer(对象属性转换)和pd-tools-validator(后端表单数据验证)

四品达通用权限系统__pd-tools-dozer(对象属性转换)和pd-tools-validator(后端表单数据验证)

四品达通用权限系统__pd-tools-dozer(对象属性转换)和pd-tools-validator(后端表单数据验证)

Dozer:如何限制映射的深度?

Dozer-对象属性映射工具类

将检索到的json转换为flutter中的自定义对象列表