Jackson Annotations - @JsonTypeInfo



Overview

@JsonTypeInfo annotation is used to indicate details of type information which is to be included in serialization and de-serialization.

Consider a case, where subclasses extends a base class and deserialization is done using base class.

class Shape {
   public String name;    
   Shape(String name){
      this.name = name;
   }
}
class Square extends Shape {
   public double length;
   Square(){
      this(null,0.0);
   }
   Square(String name, double length){
      super(name);
      this.length = length;
   }
}
class Circle extends Shape {
   public double radius;  
   Circle(){
      this(null,0.0);
   }
   Circle(String name, double radius) {
      super(name);
      this.radius = radius;
   }
}
...
String json = "{\"name\":\"CustomCircle\",\"radius\":1.0, \"type\":\"circle\"}";
Circle circle = new ObjectMapper().readerFor(Shape.class).readValue(json);

Now in order to achieve this functionality, we can use @JsonTypeName on the classes to define their type and @JsonTypeInfo to map the correct class during serialization −

@JsonTypeName("square")
static class Square extends Shape { ... }

@JsonTypeName("circle")
static class Circle extends Shape { ... }

...

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, 
   include = As.PROPERTY, property = "type") @JsonSubTypes({
      
   @JsonSubTypes.Type(value = Square.class, name = "square"),
   @JsonSubTypes.Type(value = Circle.class, name = "circle")
})

Example - Deserialization using @JsonTypeInfo

JacksonTester.java

package com.tutorialspoint;

import java.io.IOException;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonTester {
   public static void main(String args[]) throws IOException {
      Shape shape = new JacksonTester.Circle("CustomCircle", 1);
      String result = new ObjectMapper()
         .writerWithDefaultPrettyPrinter()
         .writeValueAsString(shape);
      System.out.println(result);   
      String json = "{\"name\":\"CustomCircle\",\"radius\":1.0, \"type\":\"circle\"}";
      Circle circle = new ObjectMapper().readerFor(Shape.class).readValue(json);
      System.out.println(circle.name);
   }
   @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, 
      include = As.PROPERTY, property = "type") @JsonSubTypes({
      
      @JsonSubTypes.Type(value = Square.class, name = "square"),
      @JsonSubTypes.Type(value = Circle.class, name = "circle")
   })
   static class Shape {
      public String name;    
      Shape(String name){
         this.name = name;
      }
   }
   @JsonTypeName("square")
   static class Square extends Shape {
      public double length;
      Square(){
         this(null,0.0);
      }
      Square(String name, double length){
         super(name);
         this.length = length;
      }
   }
   @JsonTypeName("circle")
   static class Circle extends Shape {
      public double radius;  
      Circle(){
         this(null,0.0);
      }
      Circle(String name, double radius) {
         super(name);
         this.radius = radius;
      }
   }
}

Output

Run the JacksonTester and verify the output −

{
   "type" : "circle",
   "name" : "CustomCircle",
   "radius" : 1.0
}
CustomCircle
Advertisements