@JsonTypeInfo
的 use = JsonTypeInfo.Id.CLASS
,会将完全限定类名序列化为类型标识符。当非 Java 客户端使用被序列化的 JSON 时,Java 类名可能不是一个好的选择。在这种情况下, use = JsonTypeInfo.Id.NAME
可以让我们使用逻辑类型名称,这样有更好的可移植性。在这种情况下,需要配合 @JsonSubTypes
和 @JsonTypeName
使用。
用于指定被注解类的逻辑名称:
@JsonTypeName("rectangle")
public class Rectangle extends Shape {
...
}
指定多态类型的可序列化的的子类型,将子类型与逻辑名称进行绑定:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes( @JsonSubTypes.Type(value = Rectangle.class, name = "rectangle"))
public abstract class Shape {
...
}
如果缺少 name
,将检查该类型的类是否包含 @JsonTypeName
注解,如果不包含或名称为空,则将构造默认名称。默认名称通常基于类名称。
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
@JsonSubTypes.Type(Rectangle.class),
@JsonSubTypes.Type(Circle.class)
})
public class Shape {
}
@JsonTypeName("rectangle")
public class Rectangle extends Shape {
private int w;
private int h;
...
}
public class Circle extends Shape {
int radius;
...
}
public class View {
private List<Shape> shapes;
...
}
public class ExampleMain {
public static void main(String[] args) throws IOException {
View v = new View();
v.setShapes(new ArrayList<>(List.of(Rectangle.of(3, 6), Circle.of(5))));
System.out.println("-- serializing --");
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(v);
System.out.println(s);
System.out.println("-- deserializing --");
View view = om.readValue(s, View.class);
System.out.println(view);
}
}
-- serializing --
{"shapes":[{"@type":"rectangle","w":3,"h":6},{"@type":"Circle","radius":5}]}
-- deserializing --
View{shapes=[Rectangle{w=3, h=6}, Circle{radius=5}]}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)...
-- serializing --
{"shapes":[{"rectangle":{"w":3,"h":6}},{"Circle":{"radius":5}}]}
-- deserializing --
View{shapes=[Rectangle{w=3, h=6}, Circle{radius=5}]}
Jackson Json - @JsonTypeInfo, using Logical Type Name with @JsonSubTypes and @JsonTypeName