javajsonjacksonjax-rs

JAXRS / Jackson polymorphic payload deserialization


I have a JAX-RS POST method handler, where I expect the payload JSON to be deserialized to a Java POJO class which is an implementation of an interface. The exact implementation of the interface to use depends on the value of attribute "type" in the json payload. Is this achievable ? Code example is given below.


public interface Entity {}

public class EntityTypeA implements Entity {}

public class EntityTypeB implements Entity {}



@POST
@Path("/entities")
@Consumes(MediaType.APPLICATION_JSON)   
@Produces(MediaType.APPLICATION_JSON) 
@JsonCreator
public String createEntity(Entity payload, @Context UriInfo uriInfo){        
    // Code to manipulate the body of the request 
    return response;
}

// payload should be an de-serialized to 
// EntityTypeA class if payload json contains {"type": "a"} and 
// to class EntityTypeB if payload json contains {"type": "b"}


Solution

  • Yes, it is achievable. Jackson provides the annotations @JsonTypeInfo and @JsonSubTypes to respectively define the property that acts as a discriminator for the possible subclasses and the value that identifies each subclass.

    In your case, the definition could look like the following:

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
    @JsonSubTypes({
            @JsonSubTypes.Type(value = EntityTypeA.class, name = "a"),
            @JsonSubTypes.Type(value = EntityTypeB.class, name = "b")
    })
    public interface Entity {
    }
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class EntityTypeA implements Entity {
        private String type;
        // ... more properties ...
    }
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class EntityTypeB implements Entity {
        private String type;
        // ... more properties ...
    }
    

    Here is also a demo at OneCompiler