Jackson 2.x 系列【5】注解大全篇一

news/2024/4/28 12:39:37/文章来源:https://blog.csdn.net/qq_43437874/article/details/136882793

有道无术,术尚可求,有术无道,止于术。

本系列Jackson 版本 2.17.0

源码地址:https://gitee.com/pearl-organization/study-jackson-demo

文章目录

    • 1. 前言
    • 2. 注解大全
      • 2.1 @JsonIgnore
      • 2.2 @JsonFormat
      • 2.3 @JsonInclude
      • 2.4 @JsonProperty
      • 2.5 @JsonAlias
      • 2.6 @JsonIgnoreType
      • 2.7 @JsonIgnoreProperties
      • 2.8 @JsonPropertyOrder
      • 2.9 @JsonGetter
      • 2.10 @JsonSetter

1. 前言

在前几篇文档中,我们学习了Jackson中几个非常重要的类,并实现了一些简单的JSON数据转换功能。在实际开发中,可能会遇到的一些个性化要求的场景,而不是简单的一些直接转换,例如,对于null值字段、敏感字段不进行序列化;Long类型的字段需要序列化为String类型(不然返回给前端时会丢失精度)…

Jackson提供了两种方式来满足个性化场景,以定制序列化/反序列化行为:

  • 配置注解Jackson提供了很多注解,用于标识Java Bean类、方法、构造器、属性
  • 配置特性枚举Jackson提供了很多xxxFeature枚举类,在读写对象中进行设置

⛹⛹⛹接下来我们了解下Jackson提供的所有注解,按照它们的使用频率顺序进行讲解。⛹⛹⛹

2. 注解大全

Jackson中的大部分注解都在jackson-annotations模块中,位于com.fasterxml.jackson.annotation包下,在jackson-databind模块中也提供了一些注解。

2.1 @JsonIgnore

@JsonIgnore标识序列化/反序列化时是否忽略该字段。

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonIgnore {// 是否忽略,默认trueboolean value() default true;
}

UserInfo类的id属性添加 @JsonIgnore

public class UserInfo{@JsonIgnore// 用户IDprivate Long id;// 省略其他......
}

进行转换:

        ObjectMapper objectMapper = new ObjectMapper();// POJO -> JSONUserInfo user = new UserInfo();user.setId(1767798780627279333L);user.setName("老三");user.setAge(25);String json = objectMapper.writeValueAsString(user);System.out.println(json);// JSON -> POJOString userJson="{\"id\":1767798780627279873,\"name\":\"坤坤\",\"age\":18,\"org\":null,\"roleList\":null}";UserInfo readUserByJson = objectMapper.readValue(userJson, UserInfo.class);System.out.println(readUserByJson);

可以看到id字段被忽略了:

{"name":"老三","age":25,"org":null,"roleList":null}
UserInfo{id=null, name='坤坤', age=18, org=null, roleList=null}

2.2 @JsonFormat

@JsonFormat标识使用格式模板进行序列化/反序列化

@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonFormat {// 默认的 Locale,java.util.Locale#getDefault()String DEFAULT_LOCALE = "##default";// 默认的 时区,来自于  java.util.TimeZoneString DEFAULT_TIMEZONE = "##default";// 格式模板String pattern() default "";// 指定序列化后的类型Shape shape() default JsonFormat.Shape.ANY;// Java Locale String locale() default "##default";// 时区String timezone() default "##default";// 是否启用“宽松”处理OptBoolean lenient() default OptBoolean.DEFAULT;// 开启某些特性Feature[] with() default {};// 关闭某些特征Feature[] without() default {};// 省略其他......
}

UserInfo类的birthdayDate属性添加 @JsonFormat注解:

    @JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")private Date birthdayDate;

序列化/反序列化结果:

{"id":1767798780627279333,"birthdayDate":"2024-03-21 09:40:33","birthdayLocalDateTime":null,"name":"老三","age":25,"org":null,"roleList":null}
UserInfo{id=1767798780627279333, birthdayDate=Thu Mar 21 09:40:33 CST 2024, birthdayLocalDateTime=null, name='老三', age=25, org=null, roleList=null}

UserInfo类的birthdayLocalDateTime属性添加 @JsonFormat注解:

    @JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")private LocalDateTime birthdayLocalDateTime;

这时会报错InvalidDefinitionException,不支持java.time.LocalDateTime

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: com.pearl.jacksoncore.demo.databind.anno.UserInfo["birthdayLocalDateTime"])

LocalDateTimeJava 8JSR 310规范下新的日期时间APIJackson核心模块并没有实现支持,需要引入jackson-datatype-jsr310模块:

        <dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jsr310</artifactId><version>2.17.0</version></dependency>

并指定序列化/反序列化器:

    @JsonDeserialize(using = LocalDateTimeDeserializer.class)@JsonSerialize(using = LocalDateTimeSerializer.class)@JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")private LocalDateTime birthdayLocalDateTime;

再次运行,结果如下:

{"id":1767798780627279333,"birthdayDate":"2024-03-21 09:47:59","birthdayLocalDateTime":"2024-03-21 09:47:59","name":"老三","age":25,"org":null,"roleList":null}
UserInfo{id=1767798780627279333, birthdayDate=Thu Mar 21 09:47:59 CST 2024, birthdayLocalDateTime=2024-03-21T09:47:59, name='老三', age=25, org=null, roleList=null}

2.3 @JsonInclude

@JsonFormat标识符合指定规格时才进行序列化

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonInclude {//   规则://   ALWAYS, 总是序列化//   NON_NULL, 不为NULL才序列化//   NON_ABSENT, NON_NULL的基础上,支持 Optional//   NON_EMPTY,  NON_ABSENT的基础上,支持集合、String//   NON_DEFAULT, 不是默认值才序列化//   CUSTOM, 自定义//   USE_DEFAULTS; 默认//  作用于类、属性Include value() default JsonInclude.Include.ALWAYS;// 作用于 Map、AtomicReference等Include content() default JsonInclude.Include.ALWAYS;// 自定义规则需要实现的过滤器Class<?> valueFilter() default Void.class;// 自定义规则需要实现的过滤器Class<?> contentFilter() default Void.class;

UserInfo类的birthdayDate属性添加 @JsonFormat注解,配置规则为NON_NULL时才进行序列化:

    @JsonInclude(JsonInclude.Include.NON_NULL)private String name;

运行结果如下:

        user.setName(null);String JsonIncludeJson = objectMapper.writeValueAsString(user);System.out.println(JsonIncludeJson);// {"birthdayDate":"2024-03-21 11:00:23","birthdayLocalDateTime":"2024-03-21 11:00:23","age":25,"org":null,"roleList":null}

2.4 @JsonProperty

@JsonProperty用于在序列化/反序列化时进行重命名。

@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonProperty {String USE_DEFAULT_NAME = "";int INDEX_UNKNOWN = -1;// 重命名后的属性名称String value() default "";String namespace() default "";boolean required() default false;// 索引位置int index() default -1;String defaultValue() default "";// 可见性配置 可以控制只在序列化或者只反序列化时生效Access access() default JsonProperty.Access.AUTO;public static enum Access {// 自动确定对此属性的读/或访问权限AUTO,// 只读READ_ONLY,// 只写WRITE_ONLY,// 可读写READ_WRITE;}
}

UserInfo类的age属性添加 @JsonProperty注解:

    @JsonProperty(value = "userAge")private Integer age;

序列化后结果:

{"userAge":25,"birthdayDate":"2024-03-21 11:43:25","birthdayLocalDateTime":"2024-03-21 11:43:25","org":null,"roleList":null}

2.5 @JsonAlias

@JsonAlias用于在反序列化时进行重命名。

@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonAlias {String[] value() default {};
}

例如JSON中属性名称为usernameUserInfo类中的属性名称为name,则可以使用@JsonAlias指定反序列化时的别名:

    @JsonAlias("username")private String name;

示例如下:

        String userAliasJson="{\"id\":1767798780627279873,\"username\":\"坤坤\",\"userAge\":18,\"org\":null,\"roleList\":null}";UserInfo readUserByAliasJson = objectMapper.readValue(userAliasJson, UserInfo.class);System.out.println(readUserByAliasJson);// UserInfo{id=null, birthdayDate=null, birthdayLocalDateTime=null, name='坤坤', age=18, org=null, roleList=null}

2.6 @JsonIgnoreType

@JsonIgnoreType作用于类,当该类作为对象属性在序列化/反序列化时会被忽略。

@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonIgnoreType {// 是否忽略,默认 tureboolean value() default true;
}

例如我们在Org类中添加该注解:

@JsonIgnoreType
public class Org {// 省略.....}

执行反序列化:

        // 6. @JsonIgnoreTypeString userJsonIgnoreTypeStr="{\"id\":1767798780627279873,\"username\":\"坤坤\",\"userAge\":18,\"org\":{\"id\":1699967647585800192,\"orgName\":\"阿里巴巴\",\"address\":\"浙江杭州\"},\"roleList\":null}";UserInfo readUserByJsonIgnoreType = objectMapper.readValue(userJsonIgnoreTypeStr, UserInfo.class);System.out.println(readUserByJsonIgnoreType);

虽然JSON内容包含了Org对象,但是被忽略掉了:

UserInfo{id=null, birthdayDate=null, birthdayLocalDateTime=null, name='坤坤', age=18, org=null, roleList=null}

2.7 @JsonIgnoreProperties

@JsonIgnoreProperties用于在序列化/反序列化时忽略某个字段属性,比@JsonIgnore功能更强,可以作用于类,配置多个忽略属性。

@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonIgnoreProperties {// 忽略的多个属性名称String[] value() default {};// 是否忽略不能识别的属性boolean ignoreUnknown() default false;// 是否允许访问属性的Getter方法,即支持Getter进行序列化boolean allowGetters() default false;// 是否允许访问属性的Setters方法,即支持Setters进行反序列化boolean allowSetters() default false;
}

Org类上标识忽略idorgName属性:

@JsonIgnoreProperties({"orgName","id"})
public class Org {// 省略.....}

案例演示,当前JSON包含了idorgName属性:

        String userIgnorePropertiesStr="{\"id\":1767798780627279873,\"username\":\"坤坤\",\"userAge\":18,\"org\":{\"id\":1699967647585800192,\"orgName\":\"阿里巴巴\",\"address\":\"浙江杭州\"},\"roleList\":null}";UserInfo readUserByIgnoreProperties = objectMapper.readValue(userIgnorePropertiesStr, UserInfo.class);System.out.println(readUserByIgnoreProperties);

反序列化时idorgName属性被忽略:

UserInfo{id=null, birthdayDate=null, birthdayLocalDateTime=null, name='坤坤', age=18, org=Org{id=null, orgName='null', address='浙江杭州'}, roleList=null}

之外还支持allowGetters 配置可以进行序列化,但反序列化时被忽略(allowSetters同理):

@JsonIgnoreProperties( value = "password",allowGetters = true)

2.8 @JsonPropertyOrder

@JsonPropertyOrder用于在序列化时进行排序。

@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonPropertyOrder {// 指定顺序String[] value() default {};// 是否按照字母表排序boolean alphabetic() default false;
}

示例代码:

@JsonPropertyOrder({"org","roleList","birthdayDate","id"})

输出结果:

{"org":null,"roleList":null,"birthdayDate":"2024-03-21 14:44:49","birthdayLocalDateTime":"2024-03-21 14:44:49","password":null,"userAge":25}

2.9 @JsonGetter

@JsonGetter@JsonProperty功能类似用于重命名,官方提示使用其替代方案@JsonProperty

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonGetter {String value() default "";
}

示例代码:

    @JsonGetter("userSex")public String getSex() {return sex;}

可以看到在序列化/反序列化时都会生效,一般使用@JsonProperty即可:

        user.setSex("男");String jsonGettersStr = objectMapper.writeValueAsString(user);System.out.println(jsonGettersStr);String jsonGetterStr="{\"userSex\":\"男\",\"id\":1767798780627279873,\"username\":\"坤坤\",\"userAge\":18,\"org\":{\"id\":1699967647585800192,\"orgName\":\"阿里巴巴\",\"address\":\"浙江杭州\"},\"roleList\":null}";UserInfo readUserByJsonGetter = objectMapper.readValue(jsonGetterStr, UserInfo.class);System.out.println(readUserByJsonGetter);

2.10 @JsonSetter

@JsonSetter@JsonProperty功能类似用于重命名,官方提示使用其替代方案@JsonProperty

@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonSetter {String value() default "";Nulls nulls() default Nulls.DEFAULT;Nulls contentNulls() default Nulls.DEFAULT;

示例代码:

    @JsonSetter("mobilePhone")public void setPhone(String phone) {this.phone = phone;}

可以看到在序列化/反序列化时都会生效:

        user.setPhone("13899996666");String jsonSettersStr = objectMapper.writeValueAsString(user);System.out.println(jsonSettersStr);String jsonSetterStr="{\"mobilePhone\":\"13899996666\",\"userSex\":\"男\",\"id\":1767798780627279873,\"username\":\"坤坤\",\"userAge\":18,\"org\":{\"id\":1699967647585800192,\"orgName\":\"阿里巴巴\",\"address\":\"浙江杭州\"},\"roleList\":null}";UserInfo readUserByJsoSetter = objectMapper.readValue(jsonSetterStr, UserInfo.class);System.out.println(readUserByJsoSetter);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_1028116.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R语言赋值符号<-、=、->、<<-、->>的使用与区别

R语言的赋值符号有&#xff1c;-、、-&#xff1e;、&#xff1c;&#xff1c;-、-&#xff1e;&#xff1e;六种&#xff0c;它们的使用与区别如下: <-’&#xff1a;最常用的赋值符号。它将右侧表达式的值赋给左侧的变量&#xff0c;像一个向左的箭头。例如&#xff0c;x …

Spring Boot 实现定时任务动态管理

前言 本文主要介绍了SpringBoot架构下动态定时任务的使用&#xff0c;定时任务表达式配置在数据库中&#xff0c;通过反射执行到目标方法。 Quartz Quartz 是一个开源的作业调度框架,支持分布式定时任务&#xff0c;Quartz定时任务据我了解可分为Trigger&#xff08;触发器&…

JavaEE企业开发新技术4

2.16 模拟Spring IOC容器功能-1 2.17 模拟Spring IOC容器功能-2 什么是IOC&#xff1f; 控制反转&#xff0c;把对象创建和对象之间的调用过程交给Spring框架进行管理使用IOC的目的&#xff1a;为了耦合度降低 解释&#xff1a; 模仿 IOC容器的功能&#xff0c;我们利用 Map…

计算机网络:物理层 - 传输媒体

计算机网络&#xff1a;物理层 - 传输媒体 物理层基本概念导引型传输媒体同轴电缆双绞线光纤 非引导型传输媒体无线电波微波红外线 物理层基本概念 在计算机网络中用来连接各种网络设备的传输媒体&#xff0c;种类众多&#xff0c;大致可以分为两类&#xff0c;一类是导引型传…

Docker进阶:Docker Swarm(集群搭建) —实现容器编排的利器

Docker进阶&#xff1a;Docker Swarm&#xff08;集群搭建&#xff09; —实现容器编排的利器 1、什么是Docker Swarm&#xff1f;2、Docker Swarm 与 Docker Compose的区别3、创建一个Swarm集群&#xff08;1-Manager&#xff0c;2-Worker&#xff09;1、资源准备2、初始化Swa…

【JavaEE初阶系列】——带你了解volatile关键字以及wait()和notify()两方法背后的原理

目录 &#x1f6a9;volatile关键字 &#x1f388;volatile 不保证原子性 &#x1f388;synchronized 也能保证内存可见性 &#x1f388;Volatile与Synchronized比较 &#x1f6a9;wait和notify &#x1f388;wait()方法 &#x1f4bb;wait(参数)方法 &#x1f388;noti…

8.HelloWorld小案例

文章目录 一、Java程序开发运行流程如何理解编译&#xff1f; 二、HelloWorld案例的编写1、新建文本文档文件&#xff0c;修改名称为HelloWorld.java。2、用记事本打开HelloWorld.java文件&#xff0c;输写程序内容。代码要跟我编写的完全保持一致。3、ctrl s 保存&#xff0c…

JavaScript基础练习题之计算数组元素的和与平均值

一、如何使用JavaScript计算数组元素的和与平均值&#xff1f; 二、正确的源程序 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>计算数组元素的和与平均值</title></head><body><h1>计算数组元…

AIGC重塑金融 | 大模型在金融行业的应用场景和落地路径

作者&#xff1a;林建明 来源&#xff1a;IT阅读排行榜 本文摘编自《AIGC重塑金融&#xff1a;AI大模型驱动的金融变革与实践》&#xff0c;机械工业出版社出版 目录 01 大模型在金融领域的 5 个典型应用场景 02 大模型在金融领域应用所面临的风险及其防范 03 AIGC 技术的科…

蓝桥杯 - 小明的背包3(多重背包)

解题思路&#xff1a; 动态规划 多重背包问题需要在01背包问题&#xff08;不重复&#xff09;的基础上多加一层循环进行遍历&#xff0c;并且dp[ j ]的式子也需要修改 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scan …

CSS及javascript

一、CSS简介 css是一门语言&#xff0c;用于控制网页的表现。 cascading style sheet:层叠样式表 二、css的导入方式 css代码与html代码的结合方式 &#xff08;1&#xff09;css导入html有三种方式&#xff1a; 1.内联样式&#xff1a;<div style"color:red&quo…

element-ui autocomplete 组件源码分享

紧接着 input 组件的源码&#xff0c;分享带输入建议的 autocomplete 组件&#xff0c;在 element-ui 官方文档上&#xff0c;没有这个组件的 api 目录&#xff0c;它的 api 是和 input 组件的 api 在一起的&#xff0c;看完源码之后发现&#xff0c;源码当中 autocomplete 组件…

MySQL中的基本SQL语句

文章目录 MySQL中的基本SQL语句查看操作创建与删除数据库和表修改表格数据库用户管理 MySQL中的基本SQL语句 查看操作 1. 查看有哪些数据库 show databases; 2.切换数据库 use 数据库名;比如切换至 mysql数据库 use mysql;3.查看数据库中的表 show tables;4.查看表中…

新能源汽车驱动电机振动噪音分析

驱动电机示例图 驱动电机的噪声主要分为空气动力噪声、电磁噪声和机械噪声。其中在高速运转时空气动力噪声是主要噪声&#xff0c;中低速运转时电磁噪声为主要噪声。 1、空气动力噪声&#xff1a; 空气噪声主要由于风扇转动&#xff0c;使空气流动、撞击、摩擦而产生&#x…

ARM-按键中断实验

代码 #include "stm32mp1xx_gic.h" #include "stm32mp1xx_exti.h" extern void printf(const char *fmt, ...); unsigned int i 0; void do_irq(void) {//获取要处理的中断的中断号unsigned int irqnoGICC->IAR&0x3ff;switch (irqno){case 99:pr…

2023年后端面试总结

备注&#xff1a;这篇文章是我在2023年年初在自己的网站上写的&#xff0c;最近在迁移技术文章&#xff0c;我感觉这个也是和咱程序员相关&#xff0c;所以今天就决定把它迁移过来。 .......................................................................分割线..........…

AJAX-综合

文章目录 同步代码和异步代码回调函数地狱解决回调函数地狱Promise-链式调用async函数和awaitasync函数和await-捕获错误 事件循环宏任务与微任务Promise.all静态方法 同步代码和异步代码 同步代码&#xff1a;逐步执行&#xff0c;需原地等待结果后&#xff0c;才继续向下执行…

后端常问面经之计算机网络

一台机器理论上能创建多少条TCP连接&#xff1f; Linux每维护一条TCP连接都要花费内存资源的&#xff0c;每一条静止状态&#xff08;不发送数据和不接收数据&#xff09;的 TCP 连接大约需要吃 3.44K 的内存&#xff0c;那么 8 GB 物理内存的服务器&#xff0c;最大能支持的 …

微服务day07 -- 搜索引擎 ( 数据聚合 + 自动补全 + 数据同步 + ES集群 )

1.数据聚合 聚合&#xff08;aggregations&#xff09;可以让我们极其方便的实现对数据的统计、分析、运算。例如&#xff1a; 什么品牌的手机最受欢迎&#xff1f; 这些手机的平均价格、最高价格、最低价格&#xff1f; 这些手机每月的销售情况如何&#xff1f; 实现这些…

R语言基础入门

1.保存或加载工作空间 改变工作目录——进行文件读写&#xff0c;默认去指定文件进行操作。&#xff08;使用R时&#xff0c;最好先设定工作目录&#xff08;setwd(),getwd()&#xff09;&#xff09; setwd(“工作文件路径”)&#xff1a;建立工作目录 getwd&#xff08;&…