bolo
bolo

Reputation: 1

Mapstruct - Mapping object inside list

I need to map an object that's inside an list of objects, but don't want to create a full builder method because the object have a lot of attributes and inner attributes.

Example:

Contract

public class ResponseContractClass {
    private List<ItemContract> items;
}
public class ItemContract {
    private AttributeContract attribute;
}
public class AttributeContract {
    private Long idContract;
    private String nameContract;
}

Impl

public class ResponseImplClass {
    private List<ItemImpl> items;
}
public class ItemImpl {
    private AttributeImpl attribute;
}
public class AttributeImpl {
    private Long idCImpl;
    private String nameImpl;
// **The problem is that this attributes signature is different from the contract ones**
}

Mapper

public interface ResponseContractMapper {


    ResponseContractClass mapFrom(ResponseImplClass response);
}

I tried someting like this, but don't work, probabbly because it's inside a list :(

public interface ResponseContractMapper {

    @Mapping(targer="items.attribute.idContract", source ="items.attribute.idImpl")
    ResponseContractClass mapFrom(ResponseImplClass response);
}

Again I'm avoiding doing this, because the object and it's attributes would be too big, but would solve the problem, that's my last resource:

public interface ResponseContractMapper {

    @Mapping(targer="items", expression ="(java(mapItems)")
    ResponseContractClass mapFrom(ResponseImplClass response);

    default List<ItemContract> mapitems(response){
       return response.stream.map(...);
    }
}

Upvotes: 0

Views: 1299

Answers (1)

Toni
Toni

Reputation: 5165

You can declare a method for mapping AttributeImpl to AttributeContract that would MapStruct use in the implementation. For example:

@Mapper(componentModel = "spring")
public interface ResponseContractMapper {

    ResponseContractClass mapFrom(ResponseImplClass response);

    @Mapping(targer="idContract", source ="idImpl")
    AttributeContract mapAttribute(AttributeImpl impl);
}

There is also a second solution that @Georgii Lvov suggested in the comments, which includes creating a separate mapper and providing it to ResponseContractMapper through the uses attribute as shown below.

@Mapper(componentModel = "spring")
public interface AttributeContractMapper {

    @Mapping(targer="idContract", source ="idImpl")
    AttributeContract mapFrom(AttributeImpl impl);
}
@Mapper(componentModel = "spring", uses=AttributeContractMapper.class)
public interface ResponseContractMapper {

    ResponseContractClass mapFrom(ResponseImplClass response);
}

Upvotes: 2

Related Questions