写点什么

jackson 学习之五:JsonInclude 注解

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

    阅读完需:约 8 分钟

jackson学习之五:JsonInclude注解

欢迎访问我的 GitHub

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

本篇概览

  1. 本文是《jackson 学习》系列第五篇,来熟悉一个常用的注解 JsonInclude,该注解的仅在序列化操作时有用,用于控制方法、属性等是否应该被序列化;

  2. 之所以用单独的一篇来写 JsonInclude 注解,是因为该注解的值有多种,每种都有不同效果,最好的学习方法就是编码实战;

  3. 先对注解的所有取值做个简介:

ALWAYS // 默认策略,任何情况都执行序列化NON_NULL // 非空NON_ABSENT // null的不会序列化,但如果类型是AtomicReference,依然会被序列化NON_EMPTY // null、集合数组等没有内容、空字符串等,都不会被序列化NON_DEFAULT // 如果字段是默认值,就不会被序列化CUSTOM // 此时要指定valueFilter属性,该属性对应一个类,用来自定义判断被JsonInclude修饰的字段是否序列化USE_DEFAULTS // 当JsonInclude在类和属性上都有时,优先使用属性上的注解,此时如果在序列化的get方法上使用了JsonInclude,并设置为USE_DEFAULTS,就会使用类注解的设置  
复制代码

源码下载

  1. 如果您不想编码,可以在 GitHub 下载所有源码,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):

  1. 这个 git 项目中有多个文件夹,本章的应用在 jacksondemo 文件夹下,如下图红框所示:

  2. jacksondemo 是父子结构的工程,本篇的代码在 annotation 子工程中,里面的 jsoninclude 这个 package 下,如下图:


  • 接下来逐个学习这些属性的效果;

ALWAYS

  • ALWAYS 表示全部序列化,如下图,null 和空字符串都会序列化:

NON_NULL

  • NON_NULL 好理解,就是值为 null 就不序列化:


NON_ABSENT

  1. NON_ABSENT 略为复杂,当实例化的对象有 Optional AtomicReference 类型的成员变量时,如果 Optional 引用的实例为空,用 NON_ABSENT 能使该字段不做序列化;

  2. Optional 是 java 用来优雅处理空指针的一个特性,本文中不做过多说明,请您自行查阅相关文档;

  3. 要让 Jackson 支持 Optional 特性,必须做两件事,首先是在 pom.xml 中添加以下依赖:

<dependency>    <groupId>com.fasterxml.jackson.datatype</groupId>    <artifactId>jackson-datatype-jdk8</artifactId>    <version>2.11.0</version></dependency>
复制代码
  1. 其次是代码中执行以下设置:

mapper.registerModule(new Jdk8Module());
复制代码
  1. 咱们先看看设置成 NON_NULL 时 jackson 对 Optional 和 AtomicReference 的处理,下面的代码中,Optional 和 AtomicReference 的引用都是空,但还是被序列化出来了:

  2. 代码不变,将 NON_NULL 改为 NON_ABSENT 试试,如下图,可见 field2 和 field3 都没有序列化了:

  • 小结 NON_ABSENT 的效果:

a. 自身为 null 的字段不会被序列化;

b. Optional 类型的字段,如果引用值为 null,该字段不会被序列化;

c. AtomicReference 类型的字段,如果引用值为 null,该字段不会被序列化;

NON_EMPTY

  • NON_EMPTY 好理解,以下情况都不会被序列化:

  1. null

  2. 空字符串

  3. 空集合

  4. 空数组

  5. Optional 类型的,其引用为空

  6. AtomicReference 类型的,其引用为空

  7. 演示代码和结果如下图,可见上述场景全部没有被序列化:

NON_DEFAULT

  1. 设置为 NON_DEFAULT 后,对保持默认值的字段不做序列化,如下图:

CUSTOM

  1. 相对其他类型,CUSTOM 略为复杂,这个值要配合 valueFilter 属性一起使用;

  2. 如下所示,JsonInclude 的 value 等于 CUSTOM 时,在序列化的时候会执行 CustomFilter 的 equals 方法,该方法的入参就是 field0 的值,如果 equals 方法返回 true,field0 就不会被序列化,如果 equals 方法返回 false 时 field0 才会被序列化

@JsonInclude(value = JsonInclude.Include.CUSTOM,                 valueFilter = CustomFilter.class)        private String field0;
复制代码
  1. 来看看 CustomFilter 类的代码,如下所示,只有 equals 方法,可见:null、非字符串、长度大于 2 这三种情况都返回 true,也就是说这三种情况下都不会被序列化

static class CustomFilter {        @Override        public boolean equals(Object obj) {            // null,或者不是字符串就返回true,意味着不被序列化            if(null==obj || !(obj instanceof String)) {                return true;            }
// 长度大于2就返回true,意味着不被序列化 return ((String) obj).length() > 2; } }
复制代码
  1. 下面贴出完整代码和结果,您就一目了然了:


  • 再次强调:valueFilter 的 equals 方法返回 true,意味着该字段不会被序列化!!!

USE_DEFAULTS

  • USE_DEFAULTS 的用法也有点绕,咱们通过对比的方法来学习;


  1. 代码如下所示,在类和成员变量上都有 JsonInclude 注解,序列化 field0 的时候,是哪个注解生效呢?:


    @JsonInclude(JsonInclude.Include.NON_EMPTY)    static class Test {
@JsonInclude(JsonInclude.Include.NON_NULL) private List<String> field0;
public List<String> getField0() { return field0; }
public void setField0(List<String> field0) { this.field0 = field0; } }
复制代码
  1. 把 field0 设置为空集合,运行代码试试,如果类上的注解生效,那么 field0 就不会被序列化(NON_EMPTY 会过滤掉空集合),如果成员变量上的注解生效,field0 就会被序列化(NON_NULL 只过滤 null,空集合不是 null),执行结果如下图,可见是成员变量上的注解生效了:

  2. 接下来保持上述代码不变,仅在 getField0 方法上添加 JsonInclude 注释,值是 USE_DEFAULTS,这样在序列化过程中,调用 getField0 方法时,就用类注解 JsonInclude 的值了,即 NON_EMPTY:

@JsonInclude(JsonInclude.Include.USE_DEFAULTS)public List<String> getField0() {   return field0; }
复制代码
  1. 执行修改后的代码,如下图所示,此时用的成员变量 field0 上的注解就不生效了,而是类注解生效,导致空集合不被序列化:

  • 小结 USE_DEFAULTS 的作用如下:

a. 类注解和成员变量注解同时存在时,以成员变量注解为准;

b. 如果对应的 get 方法也使用了 JsonInclude 注解,并且值是 USE_DEFAULTS,此时以类注解为准;

  • 至此,JsonInclude 注解的学习和实战就完成了,希望本文能给您提供参考,助您熟练使用注解来指定更精确的序列化过滤策略;

欢迎关注 InfoQ:程序员欣宸

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

发布于: 20 小时前阅读数: 21
用户头像

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

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

评论

发布
暂无评论
jackson学习之五:JsonInclude注解_4月月更_程序员欣宸_InfoQ写作平台