Search code examples
restspring-mvcjacksonjsonserializer

Polymorphic serialization using Jackson when return type is marker interface


I have a rest service which returns marker interface and this interface have multiple implementations and don't have any common property in the implementations.

    @RequestMapping(value = "/users/{userName}", method = RequestMethod.GET)
    public User getUser(@PathVariable("userName") String userName) {
        return userService.getUser(userName);
    }

User and its implementations.Note : User is marker interface.

public interface User {}

public AdminUser implements User { // some properties & its setters & getters } 

public SupportUser implements User { // some properties & its setters & getters } 

I use Jackson 1.9.1 to serialize and deserialize.

When I hit above service, I am getting below response

{}

When I debug it, I see user implementation object is prepared and sent back to Jackson for serialization.But jackson is sending empty response to browser.Can anyone suggest how to use serialize when return type is marker interface.


Solution

  • Use @JsonTypeInfo and @JsonSubTypes to deserialization polymorphic types, which maintain sub type information while serializing java object and recreate the exact sub type.

    Lets take a example, animal is a Interface and it can be an tiger or a lion, and they both extend the Animal Interface . While deserializing we want to create the exact animal type and demonstrate the use of @JsonTypeInfo and @JsonSubTypes annotations.

    @JsonTypeInfo(use=JsonTypeInfo.Id.NAME,
            include=JsonTypeInfo.As.PROPERTY,
            property="name")
    @JsonSubTypes({
            @JsonSubTypes.Type(value=Lion.class, name="lion"),
            @JsonSubTypes.Type(value=Tiger.class, name="tiger"),
    })
    public interface Animal {
    
    }
    
    @JsonTypeName("lion")
    public class Lion implements Animal {
    
        private String name;
        private String roar;
    
    //constructor & setters & getters
    }
    
    @JsonTypeName("tiger")
    public class Tiger implements Animal {
    
        private String name;
        private String purr;
    
    //constructor & setters & getters
    }
    

    Main Method :

    List<Animal> animal = new ArrayList<Animal>();
    animal.add(new Lion("lion", "roar"));
    animal.add(new Tiger("tiger", "purr"));
    animal.add(new Tiger("tiger", "purrrrrrrrr"));
    
    URL url = JacksonPolymorphicSerialization.class.getClassLoader().getResource("animals.json");
    File file = new File(url.getPath());
    
    // de-serailization sub types
    new ObjectMapper().writeValue(file, animal);
    
    // serailization animals and its subtype
    List<Animal> animals = new ObjectMapper().readValue(file, List.class);
    System.out.println(animals);
    
    
    output : [{name=lion, roar=roar}, {name=tiger, purr=purr}, {name=tiger, purr=purrrrrrrr}]
    

    Hope this helps you understanding serializing and deserializing polymorphic types using Jackson.