MapStruct:如何将所有属性映射到列表的第一个元素?

时间:2017-09-27 12:43:40

标签: mapstruct

我需要一个映射来实现这个目标:

@Mapping(source = "a", target = "result.transaction[0].a"),
@Mapping(source = "b", target = "result.transaction[0].b"),
@Mapping(source = "c", target = "result.transaction[0].c"),
...
Response dataToResponse(DataModel model);

但是这种语法不起作用(顺便说一句:这适用于Spring Bean包装器)。 像this这样的解决方案只是一个半熟的解决方案:

@AsList
public <T> List<T> asList( T in ) {
    List<T> result = new ArrayList<T>();
    if ( in!=null ) {
       result.add(in);
   }
   return result;
}

这仅适用于一个属性,因为它始终为每个属性创建一个新列表。我不需要将每个属性映射到新列表的第一个元素。该列表必须重用,但我不知道这是如何工作的。实现这一目标的正确方法是什么? 我想到了这样的事情:

@Mapping(source = "a", target = "transaction.a"),
@Mapping(source = "b", target = "transaction.b"),
@Mapping(source = "c", target = "transaction.c"),
...
Transaction dataToTransaction(DataModel model);

然后......

@Mapping([use Transaction from b4], target = "result");

但是如何从上面传递已经映射的字段? (我正在使用最新的最终版本1.1.0.Final)

3 个答案:

答案 0 :(得分:1)

显然没有干净的解决方案。所以我必须通过将以下映射排除到单独的映射器中来解决它:

@Mapping(source = "a", target = "transaction.a"),
@Mapping(source = "b", target = "transaction.b"),
@Mapping(source = "c", target = "transaction.c"),
Transaction dataToTransaction(DataModel model);

在主映射器中,我执行单独的映射器并通过表达式将其转换为列表:

@Mapping(expression = "java(Arrays.asList(SubMapper.INSTANCE.dataToTransaction(model)))", target = "result.transactions")

答案 1 :(得分:1)

只是遇到了这个问题。更优雅的解决方案是这样的:

@Mapping(source = "a", target = "transaction.a"),
@Mapping(source = "b", target = "transaction.b"),
@Mapping(source = "c", target = "transaction.c"),
Transaction dataToTransaction(DataModel model);
  • 这与上一个答案相同

剩下要做的是将单个事务映射到一个元素列表:

default List<Transaction> mapTransactionToList(Transaction source) {
     return ImmutableList.of(source);
}

现在,您可以在model定义中将List<Transaction>映射到@Mapping,然后MapStruct应该找出要做什么。

与基于“表达式”的解决方案相比,我认为它看起来更好并且更不易出错。

请注意,您可以在Mapper界面中包含代码。

答案 2 :(得分:1)

我认为使用表达式是这里的解决方法:

public interface MyMapper {
    @Mapping(target = "subjectName", expression = "java(source.getCourses().get(0).getCourseName())")
    Target map(Source source);
} 

也可以在这里查看更多信息: https://github.com/mapstruct/mapstruct/issues/1321

在我的代码中,我是这样做的:

@Mapping(expression = "java(player.getAddressBooks().get(0).getPostCode())", target = "postCode")
@Mapping(expression = "java(player.getAddressBooks().get(0).getCity())", target = "city")
@Mapping(expression = "java(player.getAddressBooks().get(0).getStreetNumber())", target = "streetNumber")
@Mapping(expression = "java(player.getAddressBooks().get(0).getStreetName())", target = "streetName")
@Mapping(expression = "java(player.getAddressBooks().get(0).getCountryISO())", target = "countryISO")