Issue
I have
// Input DTOs:
public class FeatureIn {
private String val1;
private String val2;
}
public class ContainerIn {
private List<FeatureIn> features;
}
public class PersonIn {
private String name;
private String age;
private List<ContainerIn> containers;
}
// Output DTOs:
public class FeatureOut {
private String val1;
private String val2;
}
public class PersonOut {
private String name;
private Integer age;
private List<FeatureOut> features;
}
What I have to do is to map PersonIn -> PersonOut. For name and age it is easy. For features is quite complicated. I'm receiving the PersonOut object that contains containers list (but this list is already filtered so it will always have only 1 object). I have to read first object of this list and then map List to List. In other words. PersonOut.containers.get(0).features should be mapped to PersonOut.features
I tried those two:
@Mapper(componentModel = "spring")
public interface PersonMapper {
@Mapping(target = "features", source = "containers.features")
PersonOut toPersonOut(PersonIn personIn);
}
@Mapper(componentModel = "spring")
public interface PersonMapper {
@Mapping(target = "features", expression = "java(personIn.getContainers().get(0).getFeatures())")
PersonOut toPersonOut(PersonIn personIn);
}
but it doesn't work. How can I do it?
The second solution (expression) is almost working... Mapper is generated but I have compilation fail in this line:
List<FeatureOut> features = personIn.getContainers().get(0).getFeatures();
because he tries to map List to List but types are not compatible - how can I tell him how to map it? I tried to add use = FeaturesMapper.class to my @Mapper but it was not working.
Solution
Quick solution, you can use a custom mapper by using qualifiedByName
, for example:
@Mapper(componentModel = "spring")
public interface PersonMapper {
@Mapping(target = "features", source = "containers", qualifiedByName = "mapContainers")
PersonOut toPersonOut(PersonIn personIn);
FeatureOut toFeatureIn(FeatureIn featureIn);
@Named("mapContainers")
default List<FeatureOut> mapContainers(List<ContainerIn> containers){
if(CollectionUtils.isEmpty(containers)){
return Collections.emptyList();
}
return containers.get(0).getFeatures().stream()
.map(this::toFeatureIn)
.collect(Collectors.toList());
}
}
Answered By - Youcef Laidani
Answer Checked By - Katrina (JavaFixing Volunteer)