Search code examples
spring-bootjacksonjackson-databind

Jackson Inheritance


Can't seem to figure this out. I keep getting various errors so I'll just write this with the current error I'm getting from Jackson.

public class ResponseDetail {
    private Response response;
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({
    @JsonSubTypes.Type(value = ResponseTypeOne.class, name = "ResponseTypeOne"),
    @JsonSubTypes.Type(value = ResponseTypeTwo.class, name = "ResponseTypeTwo"),
    @JsonSubTypes.Type(value = ResponseTypeThree.class, name = "ResponseTypeThree")
})
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class Response {
}

In other packages I have these three:

public class ResponseTypeOne extends Response {
     private Integer status;
}
public class ResponseTypeTwo extends Response {
    private String message;
}
public class ResponseTypeThree extends Response {
     private String value;
}

Error:

Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class com.services.models.Response]: missing type id property '@type' (for POJO property 'response')

I have tried various iterations of this @JsonTypeInfo with various includes and various property's also with Id.CLASS with no luck.


Solution

  • You need to declare how the type should be recognized.

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "@ttype")
    @JsonSubTypes({
        @JsonSubTypes.Type(value = ResponseTypeOne.class, name = "ResponseTypeOne"),
        @JsonSubTypes.Type(value = ResponseTypeTwo.class, name = "ResponseTypeTwo"),
        @JsonSubTypes.Type(value = ResponseTypeThree.class, name = "ResponseTypeThree")
    })
    
    @JsonIgnoreProperties(ignoreUnknown = true)
    public abstract class Response {
       @JsonProperty("@ttype")
       public abstract String getChildType();
    }
    
    

    And in child types do like below:

       @JsonTypeName("ResponseTypeOne")
        public class ResponseTypeOne extends Response {
            @Override
            public String getChildType() {
                return "ResponseTypeOne";
            }
        }
    

    And incoming json should be like below to enable jackson to find the correct child implementation:

    {
      //some attributes of child Response
      "@ttype": "ResponseTypeOne"
    }