mapStruct: map list to other list?

Bevor picture Bevor · Sep 18, 2017 · Viewed 19.9k times · Source

I have a list List<Payment> which I'd like to map to another list List<PaymentPlan>. These types look like this:

public class Payment {

    @XmlElement(name = "Installment")
    @JsonProperty("Installment")
    private List<Installment> installments = new ArrayList<>();

    @XmlElement(name = "OriginalAmount")
    @JsonProperty("OriginalAmount")
    private BigDecimal originalAmount;

//getters setters, more attributes
}

and....

public class PaymentPlan {
    //(Installment in different package)
    private List<Installment> installments;

    @XmlElement(name = "OriginalAmount")
    @JsonProperty("OriginalAmount")
    private BigDecimal originalAmount;

//getters setters, more attributes
}

I expect that something like this is working...

@Mappings({
    @Mapping(//other mappings...),
    @Mapping(source = "payments", target = "paymentInformation.paymentPlans")
})
ResultResponse originalResponseToResultResponse(OrigResponse originalResponse);

...but I get:

Can't map property java.util.List<Payment> to java.util.List<PaymentPlan>.
Consider to declare/implement a mapping method java.util.List<PaymentPlan> map(java.util.List<Payment> value);

I don't know how to apply this information. First I though I need to declare some extra mapping (in the same mapper class) for the lists, so MapStruct knows how to map each field of the List types like this:

@Mappings({
  @Mapping(source = "payment.originalAmount", target = "paymentInformation.paymentPlan.originalAmount")
})
List<PaymentPlan> paymentToPaymentPlan(List<Payment> payment);

...but I get error messages like

The type of parameter "payment" has no property named "originalAmount".

Obviously I do something completely wrong, since it sound like it does not even recognize the types of the List.

How can I basically map from one List to another similar List? Obviously I somehow need to combine different mapping strategies.

btw: I know how to do it with expression mapping, like...

@Mapping(target = "paymentPlans",expression="java(Helper.mapManually(payments))")

but I guess MapStruct can handle this by iself.

Answer

Filip picture Filip · Sep 18, 2017

I presume you are using version 1.1.0.Final. Your extra mapping is correct, the only difference is that you need to define a mapping without the lists MapStruct will then use that to do the mapping (the example message is a bit misleading for collections).

PaymentPlan paymentToPaymentPlan(Payment payment);

You don't even need the @Mappings as they would be automatically mapped. You might also need to define methods for the Instalment (as they are in different packages).

If you switch to 1.2.0.CR2 then MapStruct can automatically generate the methods for you.