1.场景描述
JSON作为一种轻量级的数据交换格式,其清晰和简洁的结构能够轻松地与Java对象产生映射关系。例如,一个Coke(可口可乐)类的java代码如下:
public class Coke{
String name = "Coke";
int capacity= 500;
}
用json描述该类:
{
"name":"Coke",
"capacity":500
}
而这种映射关系可以通过代码进行转换,也就是所谓的json序列化和反序列化。
序列化:是指将Java对象转换成Json文件或者Json字符串;
反序列化:是指将Json文件或者Json字符串转换成Java对象。
Java代码实现Json的序列化和反序列化并不难,尤其是现在的很多框架简化了很多的过程。下面以我常用的jackson
为例,实现简单的json序列化和反序列化:
Coke类的定义如下
public class Coke {
public String name;
public int capacity;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCapacity() {
return capacity;
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
}
下面是测试类:
public class JsonTest {
@Test
public void JsonTest() throws IOException {
ObjectMapper mapper = new ObjectMapper();
String jsonStr = " {\n" +
" \"name\":\"Coke\",\n" +
" \"capacity\":500\n" +
"}";
//json deserialization
Coke coke = mapper.readValue(jsonStr,Coke.class);
System.out.println(coke.capacity);
//json serialization
Coke coke1 = new Coke();
coke1.setName("BigCoke");
coke1.setCapacity(680);
String serializationJson = mapper.writeValueAsString(coke1);
System.out.println(serializationJson);
}
}
输出结果:
对单个类的序列化和反序列化,只要不是结构过于复杂,其操作还是比较简单的。对于此类型的序列化和反序列在这里我就不赘述了。
我们现在要讨论的情况是,假如我们现在要对json对象进行反序列化操作,但是我们并不知知道具体的json格式,也就是说我们不知道json有哪些字段。这在实际生活中很常见,比如在商店中,每件商品都有不同的属性。饮料会有容量属性,而马桶,我们一般不会去考虑"容量"这种东西吧。那我们又该如何去做这种可能性很多的反序列化呢?
问题:我们可以做反序列化,但是我们得知道这个json文件或者字符串对应的类,而上述的情况没法做到"运行前"就知道是什么商品。只有在用户付款时(运行时),我们才知道这个商品是什么。
分析:我们没法在运行前知道需要反序列化的商品
是什么,但是我们知道一共有哪些商品
可以被反序列化。而反序列化所需要的类我们也可以在工程中根据商品类型直接定义。我们要做的只是在获取到商品
时告诉它需要反序列化成哪个对象就OK了。而商品类型,我们可以根据商品名来判断。**那我们现在需要的就是一种可以根据json文件或json字符串中某个字段判断出需要反序列化成哪一种对象的方法。**幸运的是,jackson也提供了解决这类问题的方案。
2. 多态类型的处理
Jackson支持多态类型配置,在进行jackson反序列化时,可以根据配置转换成相应的子类对象。
其配置主要时通过相关的注解实现的。
@JsonTypeInfo
查看注解定义,其结构如图: