Search code examples
mapstructmapper

Java: Mapping DTOs hierarchy using MapStruct


I have Pet, Dog and Cat entity classes. Dog and Cat classes extend Pet.

Also I have PetDTO, DogDTO and CatDTO annotated with @JsonSubtype so Jackson resolves well the class of the dtos.

I want to write a mapper using MapStruct that takes a PetDTO entity (can be a DogDTO or a CatDTO) and returns a Dog or a Cat.

For me in this case, the main goal of using a mapping library is to avoid awful code using instanceof.

Any idea? Thanks!


Solution

  • Not currently possible out-of-the-box - see this ticket in mapstruct's GitHub: #366 Support for abstract class mapping or classes with base class. You can try to push it there or maybe contribute this feature yourself. Looks like a reasonable feature to ask for.

    I guess that with the current state of affairs this is your best option:

    @Mapper
    public interface PetMapper {
    
        default PetDTO toPetDto(Pet pet) {
            if (pet instanceof Dog) {
                return toDogDTO((Dog) pet);
            }
    
            if (pet instanceof Cat) {
                return toCatDTO((Cat) pet);
            }
    
            throw new IllegalArgumentException("Unknown subtype of Pet");
        }
    
        default Pet toPetEntity(PetDTO petDTO) {
            if (petDTO instanceof DogDTO) {
                return toDogEntity((DogDTO) petDTO);
            }
    
            if (petDTO instanceof CatDTO) {
                return toCatEntity((CatDTO) petDTO);
            }
    
            throw new IllegalArgumentException("Unknown subtype of PetDTO");
        }
    
        DogDTO toDogDTO(Dog dog);
        Dog toDogEntity(DogDTO dogDTO);
    
        CatDTO toCatDTO(Cat cat);
        Cat toCatEntity(CatDTO catDTO);
    }