7

jackson学习之五:JsonInclude注解_4月月更_程序员欣宸_InfoQ写作平台

 2 years ago
source link: https://xie.infoq.cn/article/4c4493d0cb26903d42a5fbc7c
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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. Optional 类型的,其引用为空

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

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

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:程序员欣宸

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

划线
评论
复制
发布于: 21 小时前阅读数: 238

版权声明: 本文为 InfoQ 作者【程序员欣宸】的原创文章。

原文链接:【https://xie.infoq.cn/article/4c4493d0cb26903d42a5fbc7c】。文章转载请联系作者。

用户头像avatar-icon-number-1.a6aec119.png

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK