多态反序列化

JSON序列化/反序列化的工具非常多,Google的Gson、Alibaba号称世界最快的FastJson、实现了Java官方的JSON Binding API(JSR 367)Eclipse YassonApache Johnzon

这些库始终都不如Jackson好用。不仅仅因为Jackson具有极致的可扩展性,可以无痛对接文本格式XMLcsv, properties, yaml和二进制格式的avro, cbor, ion, protobuf, smile,还因为他有简单易用的多态反序列化功能。Gson等库实现多态反序列化做法非常的不优雅。

多态反序列化可以让应用的设计具有机制的可扩展性。这就像schemaless的MongoDB与schemaful的MySQL的区别。

在MySQL中存储一个多态的JSON字段,可以极大的简化复杂应用的开发。

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// @JsonTypeInfo声明类型信息
// use表示用什么方式识别类型信息:
// * JsonTypeInfo.Id.NAME:用子类的name属性
// * JsonTypeInfo.Id.CLASS:用子类全类名
// * JsonTypeInfo.Id.MINIMAL_CLASS:若基类和子类在同一包类,使用类名(忽略包名)作为识别码
// * JsonTypeInfo.Id.CUSTOM:自定义识别码
// property(可选):制定识别码的属性名称
// 此属性只有当use为
// JsonTypeInfo.Id.CLASS(若不指定property则默认为@class)
// JsonTypeInfo.Id.MINIMAL_CLASS(若不指定property则默认为@c)
// JsonTypeInfo.Id.NAME(若不指定property默认为@type)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type", visible = true)
// @JsonSubTypes声明子类,name用来标记类型名,当use=JsonTypeInfo.Id.NAME时生效。
@JsonSubTypes({
@JsonSubTypes.Type(value = Vehicle.ElectricVehicle.class, name = "ELECTRIC_VEHICLE"),
@JsonSubTypes.Type(value = Vehicle.FuelVehicle.class, name = "FUEL_VEHICLE")
})
public class Vehicle {

public String type;

// standard setters and getters

public static class ElectricVehicle extends Vehicle {

String autonomy;
String chargingTime;

// standard setters and getters
}

public static class FuelVehicle extends Vehicle {

String fuelType;
String transmissionType;

// standard setters and getters
}
}

测试例子:

1
2
3
4
5
6
7
8
@Test
public void whenDeserializingPolymorphic_thenCorrect() throws JsonProcessingException {
String json = "{\"type\":\"ELECTRIC_VEHICLE\",\"autonomy\":\"500\",\"chargingTime\":\"200\"}";

Vehicle vehicle = new ObjectMapper().readerFor(Vehicle.class).readValue(json);

assertEquals(Vehicle.ElectricVehicle.class, vehicle.getClass());
}

参考文档:
Jackso官方文档:https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization
Jackson常用注解:https://www.baeldung.com/jackson-annotations#jackson-polymorphic-type-handling-annotations

本作品采用 知识共享署名 4.0 国际许可协议 进行许可。

转载时请注明原文链接:https://blog.hufeifei.cn/2022/04/Java/polymorphic-deserialization/

鼓励一下
支付宝微信