Use Java 8 optional with Mapstruct

Viewed 9212

I have these two classes:

public class CustomerEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String firstName;
    private String lastName;
    private String address;
    private int age;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

and

public class CustomerDto {
    private Long customerId;
    private String firstName;
    private String lastName;
    private Optional<String> address;
    private int age;
}

The problem is that Mapstruct doesn't recognize the Optional variable "address".

Anyone has an idea how to solve it and let Mapstruct map Optional fields?

1 Answers

This is not yet supported out of the box by Mapstruct. There is an open ticket on their Github asking for this functionality: https://github.com/mapstruct/mapstruct/issues/674

One way to solve this has been added in the comments of the same ticket: https://github.com/mapstruct/mapstruct/issues/674#issuecomment-378212135

@Mapping(source = "child", target = "kid", qualifiedByName = "unwrap")
Target map(Source source);

@Named("unwrap")
default <T> T unwrap(Optional<T> optional) {
    return optional.orElse(null);
}

As pointed by @dschulten, if you want to use this workaround while also setting the option nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, you will need to define a method with the signature boolean hasXXX() for the field XXX of type Optional inside the class which is the mapping source (explanation in the docs).

Related