jackson学习之四:WRAP_ROOT_VALUE(root对象)

欢迎访问我的GitHub

https://github.com/zq2599/blog_demos

内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;

系列文章汇总

本篇概览

本文是《jackson学习》系列的第四篇,前面学习了常用API,可以执行最基本的序列化和反序列化操作,接下来要学习的就是jackson强大的注解能力,本篇要学的是root对象特性,主要内容如下:

  1. 关于root对象
  2. 测试用的POJO类
  3. 序列化实战
  4. 反序列化实战

关于root对象(WRAP_ROOT_VALUE)

  1. 对于只有<font color="blue">id</font><font color="blue">name</font>两个字段的POJO实例来说,正常的序列化结果如下:

    { "id" : 1, "name" : "book" }

  2. jackson在序列化时,可以在上述json外面再包裹一层,官方叫做<font color="blue">WRAP_ROOT_VALUE</font>,本文中叫做<font color="red">root对象</font>,如下所示,整个json的只有一个键值对,key是<font color="blue">aaabbbccc</font>,value内部才是POJO实例的id和name字段的值:

    { "aaabbbccc" : { "id" : 2, "name" : "food" } }

提前小结

root对象特性提前做个小结,这样如果您时间有限,仅看这一节即可:

  • 先看序列化场景:
  1. 执行下面代码,jackson在序列化时会增加root对象:

    mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);

  2. root对象的key,默认是实例的类名,如果实例有JsonRootName注解,就是该注解的value值;

  3. root对象的value如下所示,相当于<font color="blue">不支持root对象时的序列化结果</font>

    { "id" : 1, "name" : "book" }

  • 再看反序列化场景:
  1. 执行下面代码,jackson在反序列化时会先解析root对象:

    mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);

  2. root对象的key,默认是实例的类名,如果实例有JsonRootName注解,就是该注解的value值;

  3. root对象的value如下所示,相当于<font color="blue">不支持root对象时用来反序列化的json字符串</font>

    { "id" : 1, "name" : "book" }

准备两个POJO类

用对比的方式可以更清楚了解JsonRootName的作用,接下来的学习咱们准备两个POJO类,一个没有JsonRootName注解,另一个有JsonRootName注解:

  1. 名为<font color="blue">Order1.java</font>的,没有JsonRootName注解:

    public class Order1 { private int id; private String name; // 省去get、set、toString方法 ... }

  2. 名为<font color="blue">Order2.java</font>的,有JsonRootName注解,value值为<font color="red">aaabbbccc</font>

    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;

序列化

  1. 需要设置WRAP_ROOT_VALUE属性,jackson才会支持root对象,JsonRootName注解才会发挥作用,设置代码如下:

    mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);

  2. 写一段代码,在不开启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");

    1 Order2 order2 = new Order2(); 2 order2. setId(2); 3 order2.setName("food"); 4 5 // 没有开启WRAP_ROOT_VALUE的时候 6 logger.info("没有开启WRAP_ROOT_VALUE\n"); 7 ObjectMapper mapper1 = new ObjectMapper(); 8 // 美化输出 9 mapper1.enable(SerializationFeature.INDENT_OUTPUT); 10 11 logger.info("没有JsonRootName注解类,序列化结果:\n\n{}\n\n", mapper1.writeValueAsString(order1)); 12 logger.info("有JsonRootName注解的类,序列化结果:\n\n{}\n\n\n\n", mapper1.writeValueAsString(order2)); 13 14 // 开启了WRAP_ROOT_VALUE的时候 15 logger.info("开启了WRAP_ROOT_VALUE\n"); 16 ObjectMapper mapper2 = new ObjectMapper(); 17 // 美化输出 18 mapper2.enable(SerializationFeature.INDENT_OUTPUT); 19 // 序列化的时候支持JsonRootName注解 20 mapper2.enable(SerializationFeature.WRAP_ROOT_VALUE); 21 22 logger.info("没有JsonRootName注解类,序列化结果:\n\n{}\n\n", mapper2.writeValueAsString(order1)); 23 logger.info("有JsonRootName注解的类,序列化结果:\n\n{}", mapper2.writeValueAsString(order2)); 24}
  3. 执行结果如下,JsonRootName在序列化时的作用一目了然:指定了root对象的key:

在这里插入图片描述

反序列化(默认设置)

  1. 在没有做任何设置的时候,下面这个字符串用来反序列化成Order2对象,会成功吗?

    { "id" : 2, "name" : "food" }

  2. 试了下是可以的:

在这里插入图片描述 3. 那下面这个字符串能反序列化成Order2对象吗?

1{ 2 "aaabbbccc" : { 3 "id" : 2, 4 "name" : "food" 5 } 6}

4. 代码和结果如下图所示,反序列化时jackson并不认识<font color="red">aaabbbccc</font>这个key,因为jackson此时并不支持root对象:

在这里插入图片描述

  • 小结:默认情况下,反序列化时json字符串不能有root对象;

反序列化(开启UNWRAP_ROOT_VALUE属性)

  1. 如果开启了UNWRAP_ROOT_VALUE属性,用于反序列化的json字符串就必须要有root对象了,开启UNWRAP_ROOT_VALUE属性的代码如下:

    mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);

  2. 代码和结果如下图,可见带有root对象的json字符串,可以反序列化成功,root对象的key就是JsonRootName注解的value属性:

在这里插入图片描述 3. 值得注意的是,上述json字符串中,root对象的key为<font color="blue">aaabbbccc</font>,这和Order2的<font color="blue">JsonRootName</font>注解的value值是一致的,<font color="red">如果不一致就会反序列化失败</font>,如下图:

在这里插入图片描述

  • 至此,jackson的WRAP_ROOT_VALUE特性就学习完成了,在web开发时这是个很常用的功能,用于在最外面包裹一层,以便整体上添加额外的内容,希望能给您带来参考;

你不孤单,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

欢迎关注公众号:程序员欣宸

微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界... https://github.com/zq2599/blog_demos

点赞
收藏

评论区

加载中...

相关推荐

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

jackson学习之三:常用API操作

欢迎访问我的GitHubhttps://github.com/zq2599/blog\_demos(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fgithub.com%2Fzq2599%2Fblog_demos)内容:所有原创文章分类汇总及配套源码,涉及Java、Doc

K8S的StorageClass实战(NFS)

欢迎访问我的GitHubhttps://github.com/zq2599/blog\_demos(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fgithub.com%2Fzq2599%2Fblog_demos)内容:所有原创文章分类汇总及配套源码,涉及Java、Doc

Flink处理函数实战之五:CoProcessFunction(双流处理)

欢迎访问我的GitHubhttps://github.com/zq2599/blog\_demos(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fgithub.com%2Fzq2599%2Fblog_demos)内容:所有原创文章分类汇总及配套源码,涉及Java、Doc

Flink的DataSource三部曲之一:直接API

欢迎访问我的GitHubhttps://github.com/zq2599/blog\_demos(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fgithub.com%2Fzq2599%2Fblog_demos)内容:所有原创文章分类汇总及配套源码,涉及Java、Doc