ModelMapper
is a popular Java library by which you can map an instance of a class to an instance of another class. By default, it maps properties with the same name. The challange is how to make the mapper maps properties whose name in source and destination is different and how to perform some operations to return customized value. For example we have two classes Person
and User
and we're going to map an object from Person
to User
.
class Person {
String firstName;
String familyName;
int age;
}
class User {
String firstName;
String lastName;
String ageStr;
}
Let's assume all getters and setters for each property have been created. The firstName
property is present on both classes, so we don't need to do anything for that property as it will be automatically mapped by ModelMapper
, unless we want the mapped value modified. The familyName
property on Person
class will be mapped to lastName
property on the User
class. To do so, create a new PropertyMap<Person, User>
. Inside, implement configure method. 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.
PropertyMap<Person, User> personMap = new PropertyMap <Person, User>() {
protected void configure() {
map().setLastName(source.getFamilyName());
}
};
modelMapper.addMappings(personMap);
What you can do inside PropertyMap
is very restricted as it uses Embedded Domain Specific Language (EDSL) to define how the values should be mapped from source to destination. Therefore you can't do many things, even using simple loop or branching may cause the following error:
ModelMapper: Ensure that method has zero parameters and does not return void
The solution for that problem is by using Converter
. The converter below formats the output to be in uppercase.
Converter<String, String> toUppercase = new
AbstractConverter<String, String>() {
protected String convert(String source) {
return source == null ? null : source.toUppercase();
}
};
Below is the example how to use the toUppercase
function.
using(toUppercase).map().setLastName(source.getFamilyName());
If you're using Java 8 or above, you can use ExpressionMapping
modelMapper.addMapping(Person::getFamilyName, User::setLastName);
It also works if the source and destination type is different.
modelMapper.addMapping(Person::getAge, User::setAgeStr);
And here's how to use converter.
Converter<String, String> toUppercase =
context -> context.getSource() == null ? null : context.getSource().toUppercase();
modelMapper.addMappings(mapper -> mapper.using(toUppercase).map(Person::getFamilyName, User::setLastName));
Alternatively, you can use lambda expression.
modelMapper.addMappings(mapper -> mapper.using(context -> (context.getSource()).toUpperCase())
.map(Person::getFamilyName, User::setLastName));