本篇介绍复杂对象下遇到的一些场景。个人总结的有以下两种。
第一种是循环引用,即A--->B---->C--->A等类似的场景。
第二种是父子类,例如User对象中存在Phone对象,Phone对象下存在dialPhone,mobilePhone等子类
1、循环引用
1.1 @JsonIdentifyInfo
它给对象添加一个ID,注解的作用是指定ID的类型。有四种值
StringIdGenerator:生成字符串ID
IntSequenceGenerator:使用序列生成器生成ID
UUIDGenerator:使用UUID生成器
PropertyGenerator:使用属性作为ID,需要设置property属性,它的值为属性名称。
例如Role类下存在User,User类下存在Role。序列化User时,在User类上添加@JsonIdentifyInfo
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class User {
}
意思是使用User的id属性作为唯一标识。property的默认值为id,上述的property可以省略。
1.2 @JsonManagedReference & @JsonBackReference
在循环引用链上,前后是一个相对的概念,@JsonManagedReference添加在之前的节点,@JsonBackReference添加在之后的节点。这样在序列化之前节点的对象时会忽略之后节点类型的属性。
例如在序列化User对象时,它的循环引用链为User--->Role---->User,在User上添加@JsonManagedReference,在Role上添加@JsonBackReference,此时在序列化User时,会忽略User的Role类型属性。
public class User {
@JsonManagedReference
private Role role;
}
public class Role {
@JsonBackReference
private User user;
}
1.3 @JsonIdentityReference
它配合@JsonIdentifyInfo使用,添加在类上时,循环引用的对象会被序列化为其ID。
例如
public class User {
@JsonIdentityReference(alwaysAsId = true)
private Role role;
}
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Role {
private String id;
@JsonBackReference
private User user;
}
当属性上添加@JsonIdentifyReference时,属性类型上必须有@JsonIndentifyInfo注解,且ID生成器类型必须为PropertyGenerator。
2、父类子类
使用示例说明,假设存在Shape父类,它的子类有Rectangle,Circle,Square。在List<Shape>集合中存在Rectangle,Circle,Square三种类型的元素,默认情况下打印时会添加类型的信息。
{
"shapes": [
{
"className": "com.example.Rectangle",
"w": 3,
"h": 6
},
{
"className": "com.example.Circle",
"radius": 5
}
]
}
2.1 @JsonTypeInfo
在shapes属性上添加@JsonTypeInfo,可以控制类型的信息。它有三个属性。
- use属性,它控制类型信息的值。它有三个值,
- Id.CLASS:类的全名,默认值
- Id.MINIMAL_CLASS:类的缩写名称
- Id.NAME: 自定义类的名称。此时需要在子类上添加@JsonTypeName。
- as属性,它控制生成的结构。它有五个值
- PROPERTY:指定属性名称,该属性的值为类信息。
- EXISTING_PROPERTY: 使用已存在的属性
- EXTERNAL_PROPERTY:TODO
- WRAPPER_OBJECT:生成JSON串的格式为 classInfo:{// 属性},例如 {"com.logicbig.Rectangle":{"w":3,"h":6}, // 后续部分}
- WRAPPER_ARRAY:类信息作为单独的一项,生成的JSON串格式为[classInfo,{// 属性},例如 [["com.logicbig.example.Rectangle",{"w":3,"h":6}]
2.2 @JsonTypeId
在属性上添加@JsonTypeId注解,该属性的值为类型的信息,通常和@JsonTypeName一起使用。
@JsonTypeName("rectangle")
public class Rectangle extends Shape {
@JsonTypeId
private String classType;
}
Json串为{"classType":"rectangle","w":3,"h":6}。
2.3 @JsonSubTypes
添加在父类上,指定包含的子类列表
// 父类
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
@JsonSubTypes.Type(value = Rectangle.class),
@JsonSubTypes.Type(value = Circle.class),
@JsonSubTypes.Type(value = Square.class)})
public abstract class Shape {
}
// 子类
@JsonTypeName("rectangle")
public class Rectangle extends Shape {
...
}