MapStruct - 单个对象中的对象的映射列表

问题描述 投票:0回答:3

我从第三方获取了一份对象列表,但它始终只包含一个对象。因此,在目标的最后,我将其创建为对象而不是列表。该对象内部包含多个列表,就像源对象一样。

这就是我尝试将列表映射到对象的方式。 ChargeTransaction 包含 orderInvoice 作为对象而不是列表。对于 ChargeTransaction 内部的列表,我创建了单独的映射器。我不想在 @afterMapping 中编写 java 代码,因为这样嵌套列表将如何映射。嵌套列表在两个对象中都是类型。

@Mapping(target = "orderInvoice", source = "basePaymentRequest.invoice.eventPayload.orderInvoices")
ChargeTransaction createInvoiceCTMapper(PaymentTriggerBaseModel basePaymentRequest, ChargeType chargeType);

错误

java: Can't map property "List<OrderInvoice> basePaymentRequest.invoice.eventPayload.orderInvoices" to "OrderInvoice orderInvoice". Consider to declare/implement a mapping method: "OrderInvoice map(List<OrderInvoice> value)".

我试过了

@Mapping(target = "orderInvoice", expression= "java(basePaymentRequest.invoice.eventPayload.orderInvoices.get(0))")

但它在 Impl 类中给出错误

 chargeTransaction.setOrderInvoice( basePaymentRequest.invoice.eventPayload.orderInvoices.get(0) );

 java: incompatible types: com.sams.oms.ng.common.models.payment.request.OrderInvoice cannot be converted to com.sams.oms.ng.common.models.payment.cosmos.OrderInvoice
java list java-11 mapstruct
3个回答
1
投票

恕我直言,解决此问题的最佳方法是使用

@Named
@Mapping#qualifiedByName

配对
@Mapper
class Mapper {

  @Mapping(target = "orderInvoice", source ="basePaymentRequest.invoice.eventPayload.orderInvoices", qualifiedByName="firstElement")
  ChargeTransaction createInvoiceCTMapper(PaymentTriggerBaseModel basePaymentRequest, ChargeType chargeType);

  @Named("firstElement")
  OrderInvoice map(List<OrderInvoice> value) {
    if(value == null) return null;
    if(value.isEmpty()) return null;
    return map(value.get(0));
  }

  abstract com.sams.oms.ng.common.models.payment.request.OrderInvoice map(com.sams.oms.ng.common.models.payment.cosmos.OrderInvoice invoice);
}

通过这种方式,您将被指示 MapStruct 使用

map(List<>)
将发票转换为单个 OrderInvoice 并抽象
map(OrderInvoice)
让 MapStruct 自动生成映射代码。

代码未经测试,因为我今天的空闲时间有限,但我希望我的示例可能有用;如果有任何错误,请随时发表评论,我会尽快纠正代码。


0
投票

如果我们使用 Java 表达式进行映射,我们需要在表达式中添加

get
()
,如下所示。

@Mapping(target = "orderInvoice", expression= "java(basePaymentRequest.getInvoice().getEventPayload().getOrderInvoices().get(0))")

0
投票

提供的第一个答案是正确的,但在这种情况下您不需要使用qualifiedByName属性和@Named注释。如果只有一个可能的候选者将一组 OrderInvoice 映射到一个 OrderInvoice,Mapstruct 足够聪明,可以自行选择您的方法。

我更喜欢将它们省略以使代码更简洁。

一般来说,当您覆盖标准映射结构转换(例如字符串到字符串,但您的自定义函数不是直接副本)或存在相同类型的多个转换时,通常只需要qualifiedByName。

第二个答案是有风险的,因为没有 null 检查,任何“get”调用都可能导致返回 null,然后执行 get 操作将导致 NPE。

© www.soinside.com 2019 - 2024. All rights reserved.