I am trying to use Mapstruct to map source object to a target list. What should be a clean mapstruct way of doing this?
Below are my DTO's.
Source DTO
@Data
class Source
{
String a;
String b;
String C;
}
Target DTO
@Data
class Target
{
String name;
List<Child> customList;
}
@Data
class Child
{
String attr1;
boolean attr2;
}
I am facing issues with Mapper Class. Trying to achieve something like below.
public interface CustomMapper
{
@Mapper(target="customList" expression="java(new Child(a,false))"
@Mapper(target="customList" expression="java(new Child(b,true))"
@Mapper(target="customList" expression="java(new Child(c,false))"
Target sourceToTarget(Source source);
}
I don't want to use qualifiedBy function like below to achieve this, as all conversion needs to be coded for each element.
List<Child> toList(Source source)
{
List<Child> customList = new ArrayList<Child>();
customList.add(new Child(source.getA(),false));
customList.add(new Child(source.getB(),true));
customList.add(new Child(source.getC(),false));
return customList;
}
In general, mapping collections with MapStruct works in the same way as for simple types. Basically, we have to create a simple interface or abstract class and declare the mapping methods. Based on our declarations, MapStruct will generate the mapping code automatically.
MapStruct is an open-source Java-based code generator which creates code for mapping implementations. It uses annotation-processing to generate mapper class implementations during compilation and greatly reduces the amount of boilerplate code which would regularly be written by hand.
To do this, we use the MapStruct unmappedTargetPolicy to provide our desired behavior when there is no source field for the mapping: ERROR: any unmapped target property will fail the build – this can help us avoid accidentally unmapped fields. WARN: (default) warning messages during the build. IGNORE: no output or ...
I have used an expression to solve this problem. The expression is to perform the mapping (for objects, straightforward for Strings), and then convert it to a list.
@Mapping(target = "names", expression = "java(Arrays.asList(map(source.getName())))")
TargetObject map(SourceObject source);
TargetName map(SourceName source)
You need to import "Arrays" class in the @Mapper definition as below.
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = "spring", imports = {Arrays.class})
I had similar use case where i want to convert and Single Object
to List
of objects.
As these are very custom requirements, will be hard for mapstruct
to provide some API for use cases like this.
I ended up implementing using default method
like this
@Mapper(componentModel = "spring")
interface MyMapper {
default List<SomeObject> from(SourceObject sourceObject) {
//Add Mappig logic here
//return the list
}
}
//If you want to use some mapper for mapping
@Mapper(componentModel = "spring")
public abstract class SomeArrayMapper {
@Autowired
SomeMapper mapper;
public SomeUser[] from(SingleObject singleObject) {
SomeUsers[] Users = new SomeUser[1];
Users[0] = mapper.toUser(singleObject);;
return Users ;
}
}
In some cases Decorators can also be useful take a look at here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With