Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MapStruct : Nested Iterable to Non-Iterable mapping?

Tags:

java

mapstruct

I found this example about Iterable to Non-Iterable mapping using Qualifier :

https://github.com/mapstruct/mapstruct-examples/tree/master/mapstruct-iterable-to-non-iterable

But how to make this mapping able to map nested properties (using dot annotation)?

E.g. mapping the field xyz of first element of a collection in the source object to a plain field on the target object?

The example define a Qualifier

@Qualifier  
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.SOURCE)  
public @interface FirstElement {
}

then define a Custom Mapper

public class MapperUtils {
    @FirstElement
    public <T> T first(List<T> in) {
        if (in != null && !in.isEmpty()) {
            return in.get(0);
        }
        else {
            return null;
        }
    }
}

and, finally, the mapping is defined as

@Mapping(target = "emailaddress", source = "emails", qualifiedBy = FirstElement.class )

But if I would like to extract from the first element of emails collection a specific field, e.g. like I would have done with code emails.get(0).getEmailAddress?

For example, I expect to write a mapping like this :

@Mapping(target = "emailaddress", source = "emails[0].emailAddress")
like image 799
lincetto Avatar asked Jul 07 '26 17:07

lincetto


1 Answers

You just need to change the MapperUtils

public class MapperUtils {
    @FirstElement
    public String firstEmailAddress(List<Person> in) {
        if (in != null && !in.isEmpty()) {
            return in.get(0).getEmailAddress();
        }
        else {
            return null;
       }
    }
}

Basically the parameter of the Annotated method should have the Iterable that you want to map from, and the return type should be the Non-Iterable that you want to map to.

If you do not want to create a custom mapping for the mapping an alternative is to use the expression attribute.

For example:

@Mapping(target = "emailaddress", expression = "emails != null && !emails.isEmpty() ? emails.get(0).getEmailAddress() : null")

However, be careful using the expression can lead to compile time problems if you make a mistake. MapStruct does not do any check for the validity of the expression and uses it as is.

like image 133
Filip Avatar answered Jul 10 '26 07:07

Filip



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!