If you are not able to have setters, you can configure ModelMapper to access by field. Just enable FieldMatching and the FieldAccessLevel as private like your list properties
modelMapper.getConfiguration()
.setFieldMatchingEnabled(true)
.setFieldAccessLevel(AccessLevel.PRIVATE);
Example:
Class FirstObject:
public class FirstObject {
private String name;
private List<FirstObjectList> objectList = new ArrayList<FirstObjectList>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<FirstObjectList> getObjectList() {
return objectList;
}
}
Class FirstObjectList:
public class FirstObjectList {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
So we are looking to map FirstObject to our SecondObject class which has exactly the same structure (properties):
Class SecondObject:
public class SecondObject {
private String name;
private List<SecondObjectList> objectList;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<SecondObjectList> getObjectList() {
return objectList;
}
}
Class SecondObjectList:
public class SecondObjectList {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Then we need to create our ModelMapper instance and configure it as field matching and private access level.
public void test(){
ModelMapper mapper = new ModelMapper();
mapper.getConfiguration().setFieldMatchingEnabled(true);
mapper.getConfiguration().setFieldAccessLevel(Configuration.AccessLevel.PRIVATE);
FirstObject firstObject = new FirstObject();
firstObject.setName("Hola");
FirstObjectList firstObjectList = new FirstObjectList();
firstObjectList.setId("1");
firstObject.getObjectList().add(firstObjectList);
SecondObject second = mapper.map(firstObject, SecondObject.class);
assertEquals(firstObject.getName(), second.getName());
assertEquals(firstObject.getObjectList().size(), second.getObjectList().size());
assertEquals(firstObject.getObjectList().get(0).getId(), second.getObjectList().get(0).getId());
}
All has been mapped perfectly. So it works.
SecondObject{name='Hola', objectList=[SecondObjectList{id='1'}]}
But if haven't enabled FieldMatching or set the Field Access Level as Private your list won't be mapped:
SecondObject{name='Hola', objectList=null}
UPDATE
If you have nested lists you mayset the naming convention as mutators to avoid multiple matching error, just configuring it like next:
modelMapper.getConfiguration()
.setSourceNamingConvention(NamingConventions.JAVABEANS_MUTATOR);
Otherwise, if you don't want to do it by field access, you can create a Converter to handle this kind of matching:
public class ListConverter implements Converter<List<SecondObject>, List<ThirdObject>> {
@Override
public List<ThirdObject> convert(MappingContext<List<SecondObject>, List<PromoConditionEntity>> context) {
//A java 8 mapping example
return context.getSource()
.stream()
.map(this::convertToThirdObject)
.collect(Collectors.toList());
}
private ThirdObject convertToThirdObject(SecondObject s) {
//your impl map SecondObject to ThirdObject
...
}
}
Finally, Don't forget to add the converter to your modelmapper isntance:
modelMapper.addConverter(new ListConverter());