How to use ModelMapper for deep inheritance objects?
Asked Answered
A

3

32

A.java

@Entity
@Getter
@Setter
@Inheritance
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, inclue=JsonTypeInfo.As.PROPERTY, property="type") 
@JsonSubTypes({
    @JsonSubTypes.Type(value=AA.class,name="aa"),
    @JsonSubTypes.Type(value=AB.class,name="ab"),
})
public abstract class A {
    @Id
    @GeneratedValue
    private Long id;

    //json ignore for getter
    @ManyToOne
    private A parent;

    @OneToMany(mappedBy="parent")
    private List<A> children;
}

AA.java

@Entity
@Getter
@Setter
@DiscriminatorValue("aa")
public class AA extends A{
    private User user;
}

AB.java

@Entity
@Getter
@Setter
@DiscriminatorValue("ab")
public class AB extends A {
    private String name;
}

Now, when I return an instance of class AB as JSON, it looks like this:

{
     "id": 1,
     "type": "ab",
     "children": [...],
     "name": "ali"
}

Since I want to use a custom User JSON, I want to use ModelMapper. All things are Ok except Absence of type.

My DTOs:

@Getter
@Setter
public class ADto {
     private Long id;

     private List<ADto> children;
}

@Getter
@Setter
public class AADto extends ADto {
     private UserDto user;
}

@Getter
@Setter
public class ABDto extends ADto {
     private String name;
}

How can I use ModelMapper and get type of class?

Andros answered 19/5, 2018 at 10:6 Comment(2)
Are you sure the example is correct? For example, AB is not used anywhere and it has only one filed but it's json has 4 fields. Could you reformat/shortly your questions so that it is clear what you need.Glycerol
@OleksandrShpota you are right, AA and AB extends class A.Andros
I
1

Possible solutions:

  1. Have you tried to add the attribute type in the parent class? This should be enough if you retrieve this field from the DB.
  2. A simple tested trick, add protected String type = this.getClass().getSimpleName().toLowerCase();. Notice that it must be protected. Here's my tested code:

    @Data
    abstract class A {
      protected String type = this.getClass().getSimpleName().toLowerCase();
    }
    
     class AB extends A {}
    
     class AA extends A {}
    
     @Test
     public void test(){
        A a1 = new AB();
        A a2 = new AA();
        assertThat(a1.getType()).isEqualTo("ab");
        assertThat(a2.getType()).isEqualTo("aa");
     }
    
Imray answered 23/5, 2018 at 15:40 Comment(0)
O
0

You can InheritanceType when you define parent class which will help to show the child type of class

Ex- A.java

@Entity
@Getter
@Setter
@Inheritance(strategy=InheritanceType.JOINED) // change needed 
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, inclue=JsonTypeInfo.As.PROPERTY, property="type") 
@JsonSubTypes({
    @JsonSubTypes.Type(value=AA.class,name="aa"),
    @JsonSubTypes.Type(value=AB.class,name="ab"),
})
public abstract class A {
Ovotestis answered 29/12, 2021 at 21:38 Comment(0)
U
0

There is now type map for solving this problem. See the type-map-inheritence documentation.

// Creates a base TypeMap with explicit mappings
TypeMap<BaseSrc, BaseDest> typeMap = modelMapper.createTypeMap(BaseSrc.class, BaseDest.class)
    .addMapping(BaseSrc::getFirstName, BaseDest::setName);

typeMap.include(SrcA.class, DestA.class)
    .include(SrcB.class, DestB.class)
    .include(SrcC.class, DestC.class);
Unawares answered 18/6, 2022 at 11:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.