写点什么

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

作者:程序员欣宸
  • 2022 年 4 月 09 日
  • 本文字数:2335 字

    阅读完需:约 8 分钟

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

欢迎访问我的 GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos


本篇概览

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


  1. 关于 root 对象

  2. 测试用的 POJO 类

  3. 序列化实战

  4. 反序列化实战

关于 root 对象(WRAP_ROOT_VALUE)

  1. 对于只有 id name 两个字段的 POJO 实例来说,正常的序列化结果如下:

{  "id" : 1,  "name" : "book"}
复制代码


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

{  "aaabbbccc" : {    "id" : 2,    "name" : "food"  }}
复制代码

提前小结

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

  • 先看序列化场景:

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

mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
复制代码


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

  2. root 对象的 value 如下所示,相当于不支持 root 对象时的序列化结果

{  "id" : 1,  "name" : "book"}
复制代码


  • 再看反序列化场景:

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

mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
复制代码


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

  2. root 对象的 value 如下所示,相当于不支持 root 对象时用来反序列化的 json 字符串

{  "id" : 1,  "name" : "book"}
复制代码

准备两个 POJO 类

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

  1. 名为 Order1.java 的,没有 JsonRootName 注解:

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


  1. 名为 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;

序列化

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

mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
复制代码


  1. 写一段代码,在不开启 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的时候 logger.info("没有开启WRAP_ROOT_VALUE\n"); ObjectMapper mapper1 = new ObjectMapper(); // 美化输出 mapper1.enable(SerializationFeature.INDENT_OUTPUT);
logger.info("没有JsonRootName注解类,序列化结果:\n\n{}\n\n", mapper1.writeValueAsString(order1)); logger.info("有JsonRootName注解的类,序列化结果:\n\n{}\n\n\n\n", mapper1.writeValueAsString(order2));
// 开启了WRAP_ROOT_VALUE的时候 logger.info("开启了WRAP_ROOT_VALUE\n"); ObjectMapper mapper2 = new ObjectMapper(); // 美化输出 mapper2.enable(SerializationFeature.INDENT_OUTPUT); // 序列化的时候支持JsonRootName注解 mapper2.enable(SerializationFeature.WRAP_ROOT_VALUE);
logger.info("没有JsonRootName注解类,序列化结果:\n\n{}\n\n", mapper2.writeValueAsString(order1)); logger.info("有JsonRootName注解的类,序列化结果:\n\n{}", mapper2.writeValueAsString(order2)); }
复制代码


  1. 执行结果如下,JsonRootName 在序列化时的作用一目了然:指定了 root 对象的 key:

反序列化(默认设置)

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

{  "id" : 2,  "name" : "food"}
复制代码


  1. 试了下是可以的:

  2. 那下面这个字符串能反序列化成 Order2 对象吗?

{  "aaabbbccc" : {    "id" : 2,    "name" : "food"  }}
复制代码


  1. 代码和结果如下图所示,反序列化时 jackson 并不认识 aaabbbccc 这个 key,因为 jackson 此时并不支持 root 对象:


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

反序列化(开启 UNWRAP_ROOT_VALUE 属性)

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

mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
复制代码


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

  2. 值得注意的是,上述 json 字符串中,root 对象的 key 为 aaabbbccc,这和 Order2 的 JsonRootName 注解的 value 值是一致的,如果不一致就会反序列化失败,如下图:


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

欢迎关注 InfoQ:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

发布于: 2022 年 04 月 09 日阅读数: 46
用户头像

搜索"程序员欣宸",一起畅游Java宇宙 2018.04.19 加入

前腾讯、前阿里员工,从事Java后台工作,对Docker和Kubernetes充满热爱,所有文章均为作者原创,个人Github:https://github.com/zq2599/blog_demos

评论

发布
暂无评论
jackson学习之四:WRAP_ROOT_VALUE(root对象)_4月月更_程序员欣宸_InfoQ写作社区