本篇介绍复杂对象下遇到的一些场景。个人总结的有以下两种。
第一种是循环引用,即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 { ... }