I have custom mapping function that maps int
to String
, but I only want it to be applied in one special case. However, it is applied to all source-fields of type int, not just the one annotated with java(...)
.
Source class:
class Source {
private int a;
private int b;
// getters etc...
}
Target class:
class Target {
private String a;
private String b;
// getters etc...
}
Mapper:
@Mapping(source="a", target="a") // should not be necessary, but to make it more explicit
@Mapping(target="b", expression = "java(modify(b))")
public abstract Target sourceToTarget(Source source);
String modify(int value) {
return "prefix_" value;
}
What I want to achieve:
target.setA(String.valueOf(a));
target.setB(modify(b));
However, the generated code does this:
target.setA(modify(a));
target.setB(modify(b));
When removing the expression and modify
, MapStruct uses String.valueOf
for both values.
I tried it with both MapStruct 1.4.2.FINAL
as well as 1.5.2.FINAL
. Both classes make use of Lombok, however, this hasn't been a problem in the past.
Is this behavior expected? If yes, how else can I make it work?
CodePudding user response:
There are two ways in which you can try :
--> @Mapping#expression
Attribute :
@Mapper(componentModel = "spring")
public interface ExampleMapper {
@Mapping(target = "b", expression = "java(modify(source.getB()))")
@Mapping(target = "a", expression = "java(String.valueOf(source.getA()))")
Target sourceToTarget(Source source);
default String modify(int value) {
return "prefix_" value;
}
}
It has generated this code :
@Component
public class ExampleMapperImpl implements ExampleMapper {
@Override
public Target sourceToTarget(Source source) {
if ( source == null ) {
return null;
}
Target target = new Target();
target.setB( modify(source.getB()) );
target.setA( String.valueOf(source.getA()) );
return target;
}
}
--> Try with @Named
:
@Mapper(componentModel = "spring")
public interface ExampleMapper {
@Mapping(source = "a", target = "a")
@Mapping(target = "b", expression = "java(modify(source.getB()))")
Target sourceToTarget(Source source);
@Named("any-name")
default String modify(int value) {
return "prefix_" value;
}
}
Note : I have used @Named
on modify(int value)
method so that it can't be used by any mapping unless mentioned via qualifiedByName
or explicitly called via expression
.
It has generated this code :
@Component
public class ExampleMapperImpl implements ExampleMapper {
@Override
public Target sourceToTarget(Source source) {
if ( source == null ) {
return null;
}
Target target = new Target();
target.setA( String.valueOf( source.getA() ) );
target.setB( modify(source.getB()) );
return target;
}
}