Json 的序列化和反序列化是我们常见的操作,很多库都提供了这样的能力帮助我们完成这样的操作。但业务有时可能变得稍微有些复杂,需要将一个抽象类的子类实例序列化成一个 Json,也需要将一个 Json 反序列化成一个抽象类。而在反序列化的时候,就需要找到真正的子类。
Jackson
是 Java 中常用的一种进行 Json 序列化和反序列化的库,它能否面对这样的业务呢?
业务假设
假设我们有这样的类结构关系:
代码写出来长这样:
package cn.gaoyuexiang.practice.jackson.inheritance;
@Data
public abstract class Ticket {
private TicketType type;
}
@Data
@EqualsAndHashCode(callSuper=true)
public class BugReportingTicket extends Ticket {
private String productName;
private String stepToReproduce;
}
@Data
@EqualsAndHashCode(callSuper=true)
public class QuestionTicket extends Ticket {
private String description;
}
可以在 https://github.com/kbyyd24/jackson-inheritance-practice[1] 看到完整代码
接下来所有的序列化和反序列化操作,都是针对类型为 Ticket
的变量来执行的,而不考虑真实的类型。
序列化
序列化不会遇到任何挑战。因为不管变量的真实类型是什么,Jackson 总是会通过所有的 getter
方法来找到所有的属性和值,并序列化到 Json 中。
反序列化
反序列化就不同了,因为程序不知道 Json 应该对应到哪一个子类,所以我们会写出这样的代码:
Ticket ticket = new ObjectMapper().readValue(json, Ticket.class);
而抽象类又不能创建出实例,所以这一行代码就会因为这个限制而出错。
为了让这一行代码成功执行,为 ticket
变量找到真正的类型,我们就需要使用 @JsonTypeInfo
注解。