我从第三方获取了一份对象列表,但它始终只包含一个对象。因此,在目标的最后,我将其创建为对象而不是列表。该对象内部包含多个列表,就像源对象一样。
这就是我尝试将列表映射到对象的方式。 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
恕我直言,解决此问题的最佳方法是使用
@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 自动生成映射代码。
代码未经测试,因为我今天的空闲时间有限,但我希望我的示例可能有用;如果有任何错误,请随时发表评论,我会尽快纠正代码。
如果我们使用 Java 表达式进行映射,我们需要在表达式中添加
get
和 ()
,如下所示。
@Mapping(target = "orderInvoice", expression= "java(basePaymentRequest.getInvoice().getEventPayload().getOrderInvoices().get(0))")
提供的第一个答案是正确的,但在这种情况下您不需要使用qualifiedByName属性和@Named注释。如果只有一个可能的候选者将一组 OrderInvoice 映射到一个 OrderInvoice,Mapstruct 足够聪明,可以自行选择您的方法。
我更喜欢将它们省略以使代码更简洁。
一般来说,当您覆盖标准映射结构转换(例如字符串到字符串,但您的自定义函数不是直接副本)或存在相同类型的多个转换时,通常只需要qualifiedByName。
第二个答案是有风险的,因为没有 null 检查,任何“get”调用都可能导致返回 null,然后执行 get 操作将导致 NPE。