MapStruct nested object, create target object only if source element is not null
Asked Answered
R

2

5

I want to map nested java objects. Customer.address.houseNumber to userDTO.homeDTO.addressDTO.houseNo.

Expectation: If and only if Customer.address.houseNumber is not null, then create homeDTO object under userDTO. Otherwise, do not create any target objects.

Problem: I have used "NullValueCheckStrategy.ALWAYS"in the mapper, but mapstruct is checking if address is not null then it creates homeDTO. Inside the address, the houseNumber is null. I would like the null check till the houseNumber (leaf/last level object) and then create the target objects.

How can I achieve this?

Here is mapping that I am using.

@Mapper( nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS )
public interface Customer2UserMapper {

    @Mapping(source="address.houseNumber", target="homeDTO.addressDTO.houseNo" )
    void mapCustomerHouse(Customer customer, @MappingTarget  UserDTO userDTO)  ;

}

The generated code is in https://github.com/mapstruct/mapstruct/issues/1303

Receiver answered 28/9, 2017 at 13:6 Comment(2)
There are some typos (error) in the code that you attached, e.g. customer.getAddress()=.getHouseNumber()Irmine
Thank you Andrii. Corrected it.Receiver
F
5

This is something similar as in mapstruct/mapstruct#879. Currently what you are looking for is not possible.

A way to do it would be do have an @AfterMapping method that will set it back to null if the address.houseNumber is null

Framing answered 2/10, 2017 at 21:9 Comment(5)
Thank you Filip. But @AfterMapping will be extra code to check if src is null and then set target to null. I have 1000 elements to be mapped, for each element i can not do this check.Receiver
I know that it will be extract code, but currently that is the only way to solve the problem that you have. That is why I linked you to the issue, where you can comment and upvote.Framing
After almost 2.5 years is there any update on the same? Thanks in advance.Assembler
@Assembler github.com/mapstruct/mapstruct/issues/1306Castano
ugly, but setting it back to null in @AfterMapping worked for me. could probably do something similar with a Decorator tooCornfield
C
1

You can do this by using nested mappers. mapCustomerToHouse mapper will use mapHouseNumberToHouseNo mapper to map houseNumber to homeDTO, since they are not the same type. The nested mapper will check whether houseNo is null and if so, not instantiate the HomeDTO object:

@Mapping(source="address.houseNumber, target="homeDTO" )
void mapCustomerHouse(Customer customer, @MappingTarget  UserDTO userDTO)  ;

@Mapping(source="houseNumber, target="addressDTO.houseNo" )
HomeDTO mapHouseNumberToHouseNo(Integer houseNumber)
Cispadane answered 19/12, 2022 at 10:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.