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

简介: 了解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. 对于只有idname两个字段的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. 试了下是可以的:

在这里插入图片描述

  1. 那下面这个字符串能反序列化成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属性:

在这里插入图片描述

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

在这里插入图片描述

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

欢迎关注阿里云开发者社区博客:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...
相关文章
|
7月前
|
API Android开发
Android高手进阶教程(十五)之---通过Location获取Address的使用!
Android高手进阶教程(十五)之---通过Location获取Address的使用!
74 1
|
Android开发
我的Android进阶之旅------>adbd cannot run as root in production builds 的解决方法
今天用adb root命令时候,报了错误:adbd cannot run as root in production builds C:\Documents and Settings\Administrator>adb root adbd cannot ...
4616 0
|
6月前
|
XML 开发框架 人工智能
C#/.NET/.NET Core拾遗补漏合集(24年5月更新)
C#/.NET/.NET Core拾遗补漏合集(24年5月更新)
|
监控 安全 Linux
docker 命令 --cap-add NET_ADMIN 什么作用
`--cap-add NET_ADMIN` 是 Docker 容器运行时的一个参数,用于添加网络管理员权限(NET_ADMIN capability)给容器。 在 Linux 系统中,每个进程都有特定的权限来执行特定的操作。网络管理员权限是一种较高级的权限,它允许容器内的进程执行一些需要网络配置和管理的操作,例如配置网络接口、修改路由表、设置防火墙规则等。 通过添加 `--cap-add NET_ADMIN` 参数,Docker 容器将获得网络管理员权限,使其能够执行更高级的网络操作。这对于某些特定的应用场景,如网络监控、网络测试等非常有用。 需要注意的是,使用网络管理员权限可能存在安全
1833 1
|
7月前
|
Android开发
Android修改源码实现root
Android修改源码实现root
105 0
|
JSON Java 程序员
jackson学习之四:WRAP_ROOT_VALUE(root对象)
了解jackson的WRAP_ROOT_VALUE(root对象)特性
jackson学习之四:WRAP_ROOT_VALUE(root对象)
|
Kubernetes 容灾 应用服务中间件
【k8s 系列】k8s 学习十一,Label,RC,HPA
上面简单说了一下 pod 的基本知识点,待到后面会使用到 pod 的一些高阶知识点的时候,还可以再细细琢磨底层原理
120 0
|
编解码
wrf模式学习记录--如何计算三层嵌套中的e_sn/e_we/ i_parent_start/ j_parent_start
在此记录一下关于wrf模式中如何计算嵌套网格的格点数,即e_sn / e_we
wrf模式学习记录--如何计算三层嵌套中的e_sn/e_we/ i_parent_start/ j_parent_start
|
安全 Shell Android开发
【Android 逆向】Android 权限 ( adb 降权相关的属性 | ro.secure 属性 | ro.debuggable 属性 | service.adb.root 属性 )
【Android 逆向】Android 权限 ( adb 降权相关的属性 | ro.secure 属性 | ro.debuggable 属性 | service.adb.root 属性 )
901 0
【Android 逆向】Android 权限 ( adb 降权相关的属性 | ro.secure 属性 | ro.debuggable 属性 | service.adb.root 属性 )
|
Android开发
6-VI--ListView琐碎小知识点汇总
1、ListView不显示蓝色阴影: 强迫症的你有没有很讨厌这个阴影,反正我是不喜欢,去除方法: 阴影.png listview.setOverScrollMode(ListView.
1297 0