ModelMapper: Choose mapping based on Child class
Well, the solution I found uses converters. In this case modelMapper
doesn't try to create a new instance of abstract class, but uses the converter directly.
You can put all the converters in same place
modelMapper.createTypeMap(ChildA.class, ParentDTO.class)
.setConverter(mappingContext -> modelMapper.map(mappingContext.getSource(), ClassADTO.class));
modelMapper.createTypeMap(ChildB.class, ParentDTO.class)
.setConverter(mappingContext -> modelMapper.map(mappingContext.getSource(), ClassBDTO.class));
....
I would use ObjectMapper instead of ModelMapper.
In Parent class add the possibility to get the discriminator value.
//..
public class Parent {
@Column(name = "type", insertable = false, updatable = false)
private String type;
//getters and setters
}
Your ParentDTO should be mapped to Child(*)DTO
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = ChildADTO.class, name = "child_a"),
@JsonSubTypes.Type(value = ChildBDTO.class, name = "child_b")
})
public abstract class ParentDTO {
// ..
}
in the conversion service/method add an object mapper with ignore unknown (to ignore what you did not declare in your DTO class)
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
just simply call :
Parent parent = // get from repository
ParentDTO parentDTO = objectMapper.readValue(objectMapper.writeValueAsBytes(parent), ParentDTO.class);
In this way, your ParentDTO is always instantiated with the right type.