欢迎访问我的GitHub
内容:所有原创文章分类和汇总,及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;
本篇概览
本文是《jackson学习》系列的第四篇,前面学习了常用API,可以执行最基本的序列化和反序列化操作,接下来要学习的就是jackson强大的注解能力,本篇要学的是root对象特性,主要内容如下:
- 关于root对象
- 测试用的POJO类
- 序列化实战
- 反序列化实战
关于root对象(WRAP_ROOT_VALUE)
- 对于只有id和name两个字段的POJO实例来说,正常的序列化结果如下:
{ "id" : 1, "name" : "book"}
- jackson在序列化时,可以在上述json外面再包裹一层,官方叫做WRAP_ROOT_VALUE,本文中叫做root对象,如下所示,json最外层只有一个键值对,key是aaabbbccc,value内部才是POJO实例的id和name字段的值:
{ "aaabbbccc" : { "id" : 2, "name" : "food" }}
提前小结
提前对root对象特性做个小结,这样如果您时间有限,仅看这一节即可:
- 先看序列化场景:
- 执行下面代码后,jackson在序列化时会增加root对象:
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
- root对象的key,默认是实例的类名,如果实例有JsonRootName注解,就是该注解的value值;
- root对象的value如下所示,相当于不支持root对象时的序列化结果:
{ "id" : 1, "name" : "book"}
- 再看反序列化场景:
- 执行下面代码后,jackson在反序列化时会先解析root对象:
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
- root对象的key,默认是实例的类名,如果实例有JsonRootName注解,就是该注解的value值;
- root对象的value如下所示,相当于不支持root对象时用来反序列化的json字符串:
{ "id" : 1, "name" : "book"}
接下来通过实战来学习;
准备两个POJO类
用对比的方式可以更清楚了解JsonRootName的作用,接下来的学习咱们准备两个POJO类,一个没有JsonRootName注解,另一个有JsonRootName注解:
- 名为Order1.java的,没有JsonRootName注解:
public class Order1 { private int id; private String name;// 省去get、set、toString方法...}
- 名为Order2.java的,有JsonRootName注解,value值为aaabbbccc:
import com.fasterxml.jackson.annotation.JsonRootName;@JsonRootName(value = "aaabbbccc")public class Order2 {private int id; private String name;// 省去get、set、toString方法...}
- 可见Order1和Order2的代码是一致的,唯一的不同是Order2带有注解JsonRootName;
序列化
- 需要设置WRAP_ROOT_VALUE属性,jackson才会支持root对象,JsonRootName注解才会发挥作用,设置代码如下:
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
- 写一段代码,先在不开启WRAP_ROOT_VALUE属性的时候执行序列化,然后再开启WRAP_ROOT_VALUE属性执行序列化,对比试试:
public static void main(String[] args) throws Exception { // 实例化Order1和Order2 Order1 order1 = new Order1(); order1. setId(1); order1.setName("book"); Order2 order2 = new Order2(); order2. setId(2); order2.setName("food"); // 没有开启WRAP_ROOT_VALUE的时候 ("没有开启WRAP_ROOT_VALUE"); ObjectMapper mapper1 = new ObjectMapper(); // 美化输出 mapper1.enable(SerializationFeature.INDENT_OUTPUT); ("没有JsonRootName注解类,序列化结果:{}", mapper1.writeValueAsString(order1)); ("有JsonRootName注解的类,序列化结果:{}", mapper1.writeValueAsString(order2)); // 开启了WRAP_ROOT_VALUE的时候 ("开启了WRAP_ROOT_VALUE"); ObjectMapper mapper2 = new ObjectMapper(); // 美化输出 mapper2.enable(SerializationFeature.INDENT_OUTPUT); // 序列化的时候支持JsonRootName注解 mapper2.enable(SerializationFeature.WRAP_ROOT_VALUE); ("没有JsonRootName注解类,序列化结果:{}", mapper2.writeValueAsString(order1)); ("有JsonRootName注解的类,序列化结果:{}", mapper2.writeValueAsString(order2)); }
- 执行结果如下,JsonRootName在序列化时的作用一目了然:指定了root对象的key:
反序列化(默认设置)
- 在没有做任何设置的时候,下面这个字符串用来反序列化成Order2对象,会成功吗?
{ "id" : 2, "name" : "food"}
- 试了下是可以的:
- 那下面这个字符串能反序列化成Order2对象吗?
{ "aaabbbccc" : { "id" : 2, "name" : "food" }}
- 代码和结果如下图所示,反序列化时jackson并不认识aaabbbccc这个key,因为jackson此时并不支持root对象:
- 小结:默认情况下,反序列化时json字符串不能有root对象;
反序列化(开启UNWRAP_ROOT_VALUE属性)
- 如果开启了UNWRAP_ROOT_VALUE属性,用于反序列化的json字符串就必须要有root对象了,开启UNWRAP_ROOT_VALUE属性的代码如下:
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
- 代码和结果如下图,可见带有root对象的json字符串,可以反序列化成功,root对象的key就是JsonRootName注解的value属性:
- 值得注意的是,上述json字符串中,root对象的key为aaabbbccc,这和Order2的JsonRootName注解的value值是一致的,如果不一致就会反序列化失败,如下图:
至此,jackson的WRAP_ROOT_VALUE特性就学习完成了,希望能给您带来参考;