Lets assume I have class MySource
:
public class MySource {
public String fieldA;
public String fieldB;
public MySource(String A, String B) {
this.fieldA = A;
this.fieldB = B;
}
}
and I would like to translate it to object MyTarget
:
public class MyTarget {
public String fieldA;
public String fieldB;
}
using default ModelMapper settings I can achieve it in the following way:
ModelMapper modelMapper = new ModelMapper();
MySource src = new MySource("A field", "B field");
MyTarget trg = modelMapper.map(src, MyTarget.class); //success! fields are copied
It can happen however, that MySource
object will be null
. In this case, MyTarget will be also null
:
ModelMapper modelMapper = new ModelMapper();
MySource src = null;
MyTarget trg = modelMapper.map(src, MyTarget.class); //trg = null
I would like to specify custom mapping in such a way, that (pseudo code):
MySource src != null ? [perform default mapping] : [return new MyTarget()]
Does anybody have idea how to write an appropriate converter to achieve that?
For each property you want to map, call map() , which is of type User (the destination class), then call the setter setLastName with source. getFamilyName() as the argument. Then, add the PropertyMap mapping to the ModelMapper instance. The solution for that problem is by using Converter .
I believe that ModelMapper is based on reflection and performs the mapping during runtime. Whereas MapStruct is a code generator which generates the mapping code (java classes) during compilation time. So naturally if you are worried about performance then MapStruct is the clear choice.
ModelMapper consists of two separate processes: the matching process, where a source and destination type's properties are matched to each other, and the mapping process where matched property values are converted from a source to destination object.
When we use the starter, we just add a Gradle dependency and then autowire the ModelMapper instance in our controllers. @Controller public class TaskController { @Autowired private TaskRepository taskRepository; @Autowired private ModelMapper modelMapper; ... }
It is not possible using ModelMapper directly because ModelMapper map(Source, Destination)
method checks if source is null, in that case it throws an exception...
Take a look to ModelMapper Map method implementation:
public <D> D map(Object source, Class<D> destinationType) {
Assert.notNull(source, "source"); -> //IllegalArgument Exception
Assert.notNull(destinationType, "destinationType");
return mapInternal(source, null, destinationType, null);
}
I propose extends ModelMapper class and override map(Object source, Class<D> destinationType)
like this:
public class MyCustomizedMapper extends ModelMapper{
@Override
public <D> D map(Object source, Class<D> destinationType) {
Object tmpSource = source;
if(source == null){
tmpSource = new Object();
}
return super.map(tmpSource, destinationType);
}
}
It checks if source is null, in that case it initializes then it calls super map(Object source, Class<D> destinationType)
.
Finally, you could use your customized mapper like this:
public static void main(String args[]){
//Your customized mapper
ModelMapper modelMapper = new MyCustomizedMapper();
MySource src = null;
MyTarget trg = modelMapper.map(src, MyTarget.class); //trg = null
System.out.println(trg);
}
The output would be a new MyTarget()
:
Output Console: NullExampleMain.MyTarget(fieldA=null, fieldB=null)
Thus it is initialized.
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