Jackson 2.x 系列【6】注解大全篇二

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

本系列Jackson 版本 2.17.0

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

文章目录

    • 注解大全
      • 2.11 @JsonValue
      • 2.12 @JsonKey
      • 2.13 @JsonAnySetter
      • 2.14 @JsonAnyGetter
      • 2.15 @JacksonInject
      • 2.16 @JsonCreator
      • 2.17 @JsonTypeInfo
      • 2.18 @JsonSubTypes
      • 2.19 @JsonTypeName
      • 2.20 @JsonTypeId

注解大全

2.11 @JsonValue

@JsonValue用于将整个对象序列化为单个值,常用于只包含单个值的简单对象或枚举类型。Jackson 会忽略对象的其他属性和字段,只序列化由 @JsonValue 注解指定的方法或属性值。

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonValue {boolean value() default true;
}

例如当前有个性别枚举类:

public enum GenderEnum {MAN("man", "男"),WOMAN("woman", "女");GenderEnum(String code, String desc) {this.code = code;this.desc = desc;}private String code;private String desc;// 省略getter\serter.......
}

用户对象类包含了性别枚举类属性:

    GenderEnum gender;

设置性别并进行序列化:

        user.setGender(GenderEnum.WOMAN);String jsonValuesStr = objectMapper.writeValueAsString(user);System.out.println(jsonValuesStr);

输出时可以看到枚举类被序列化为WOMAN,我们期望输出的是

{"gender":"WOMAN","userAge":25,"mobilePhone":"13899996666"}

在枚举类字段上添加@JsonValue

    @JsonValueprivate String desc;

再次执行,可以看到将整个枚举类序列化为了一个值:

{"gender":"女","userAge":25,"mobilePhone":"13899996666"}

2.12 @JsonKey

@JsonKey也是将某个对象序列化为单个值,但是仅在实例作为Map类型中的键进行序列化时有效。

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonKey {boolean value() default true;
}

例如下方代码:

        Org org1=new Org();org1.setId(1765672919981232128L);org1.setOrgName("阿里巴巴");Org org2=new Org();org2.setId(1772078846569590784L);org2.setOrgName("支付宝");Map<Org, String> map = new HashMap<>();map.put(org1,"顶级机构");map.put(org2,"下级机构");String orgStr = objectMapper.writeValueAsString(map);System.out.println(orgStr);

序列化后输出如下:

{"Org{id=1765672919981232128, orgName='null', address='null'}":"顶级机构","Org{id=1772078846569590784, orgName='null', address='null'}":"下级机构"}

Org属性上添加@JsonKey注解,表示序列化该对象时,使用orgName值作为Map中的键:

    @JsonKeyprivate String orgName;

输出如下:

{"阿里巴巴":"顶级机构","支付宝":"下级机构"}

2.13 @JsonAnySetter

@JsonAnySetter用于反序列化时,将被忽略无法反序列化的内容,统一存放在Map集合中。

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonAnySetter {boolean enabled() default true;
}

UserInfo中添加一个Map属性,Setter方法使用@JsonAnySetter标识:

    private Map<String,Object> collect =new HashMap<>();@JsonAnySetterpublic void setCollect(String key,Object value) {this.collect.put(key,value);}

JSON中有一个idCard属性是UserInfo类没有的:

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

这时idCard会被存放到Map中:
在这里插入图片描述

2.14 @JsonAnyGetter

@JsonAnyGetter则用于在序列化时,将Map集合中的内容以对象属性的方式进行输出。

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonAnyGetter {boolean enabled() default true;
}

直接将上面@JsonAnySetter反序列化的对象进行序列化时,和之前的JSON内容不一致:

{"collect":{"idCard":"43268825255522222","id":1767798780627279873},"userAge":18,"userSex":"男","mobilePhone":null}

添加@JsonAnyGetter

    @JsonAnyGetterpublic Map<String, Object> getCollect() {return collect;}

输出结果如下:

{"mobilePhone":null,"idCard":"43268825255522222","id":1767798780627279873}

2.15 @JacksonInject

@JacksonInject标识该属性值不是直接从JSON数据中读取,而是通过注入的方式,根据ObjectMapper的配置或其他机制提供。

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JacksonInject {// 逻辑ID,根据该ID从配置或者其他环境中查询对应的值并注入String value() default "";OptBoolean useInput() default OptBoolean.DEFAULT;// 省略........
}

应用场景:

  • 依赖注入:在对象创建时,可能有一些值需要通过外部机制(如Spring框架的依赖注入)提供,而不是从JSON中解析,这时可以使用@JacksonInject来标记这些属性
  • 默认值:有时我们可能希望为某些属性提供默认值,而这些默认值不是从JSON数据中读取的。使用@JacksonInject可以确保在没有从JSON中找到对应值的情况下使用这些默认值。
  • 上下文相关值:当处理与特定上下文相关的数据时,可能需要将某些上下文信息注入到对象中。这些上下文信息可能不是JSON数据的一部分,而是由调用方或应用程序的其他部分提供的

添加@JacksonInject注解:

    @JacksonInject(value = "phone")private String phone;

使用InjectableValues注入默认值:

        // 设置默认值InjectableValues.Std injectableValues = new InjectableValues.Std();injectableValues.addValue("phone","13788889999");objectMapper.setInjectableValues(injectableValues);// 反序列化String jsonInjectStr="{}";UserInject readUserByInject = objectMapper.readValue(jsonInjectStr, UserInject.class);System.out.println(readUserByInject);

输出结果如下:

User{name='null', phone='13788889999'}

2.16 @JsonCreator

@JsonCreator指定反序列化时构造对象实例使用的方法。

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonCreator {// 构建者类型Mode mode() default JsonCreator.Mode.DEFAULT;public static enum Mode {DEFAULT,DELEGATING,PROPERTIES,DISABLED;private Mode() {}}
}

添加无参、有参的构造方法:

    public UserInject() {System.out.println("无参构造");}public UserInject(String name, String phone) {this.name = name;this.phone = phone;System.out.println("有参构造");}

进行序列化:

        String jsonCreatorStr="{\"phone\":\"13566666665\",\"name\":\"张三\"}";UserInject readUserByCreator = objectMapper.readValue(jsonCreatorStr, UserInject.class);System.out.println(readUserByCreator);

输出结果中,可以看到默认使用的是无参构造和setter方法:

无参构造
setPhone
setName
User{name='张三', phone='13566666665'}

可以使用 @JsonCreator指定使用的构造函数,使用@JsonProperty指定属性映射关系:

    @JsonCreatorpublic UserInject(@JsonProperty("name") String name, @JsonProperty(value = "phone") String phone)  {this.name = name;this.phone = phone;System.out.println("有参构造");}

输出结果如下:

有参构造
User{name='张三', phone='13566666665'}

2.17 @JsonTypeInfo

@JsonTypeInfo用于多态类型时指定子类类型,以便在反序列化时能够准确地重建原始对象类型。

@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonTypeInfo {// 定义如何包含类型信息Id use();// 定义类型信息应该在哪里包含As include() default JsonTypeInfo.As.PROPERTY;// 当 use 设置为 Id.AS_PROPERTY 时,这个属性定义了包含类型信息的 JSON 属性的名称String property() default "";// 当无法确定具体的子类型时,使用的默认实现类Class<?> defaultImpl() default JsonTypeInfo.class;// 定义是否传递类型标识符值的属性boolean visible() default false;// 确定在其子类型的多态反序列化过程中是否应严格要求类型IDOptBoolean requireTypeIdForSubtypes() default OptBoolean.DEFAULT;

例如,定义了一个抽象类Person,它有两个类型StudentTeacher,并定义一个返回对象PersonVO定义了属性为Person实例集合:

public abstract class Person {public String name;// getters and setters  
}public class Student extends Person{
}public class Teacher extends Person{
}public class PersonVO {List<Person> personList;// getters and setters  
}

执行序列化和反序列化操作:

        Student student=new Student();student.setName("坤坤童鞋");Teacher teacher=new Teacher();teacher.setName("悠上老师");List<Person> personList=new ArrayList<>();personList.add(student);personList.add(teacher);PersonVO personVO=new PersonVO();personVO.setPersonList(personList);String jsonStrByPerson = objectMapper.writeValueAsString(personVO);System.out.println(jsonStrByPerson);PersonVO readUserByPerson = objectMapper.readValue(jsonStrByPerson, PersonVO.class);System.out.println(readUserByPerson);

反序列化时,直接调用抽象类Person的构造导致报错(应该调用具体的实现类的构造):

{"personList":[{"name":"坤坤童鞋"},{"name":"悠上老师"}]}
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.pearl.jacksoncore.demo.databind.anno.Person` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type informationat [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 16] (through reference chain: com.pearl.jacksoncore.demo.databind.anno.PersonVO["personList"]->java.util.ArrayList[0])

Person类上添加@JsonTypeInfoproperty配置表示使用@class作为类型属性名,JsonTypeInfo.Id.CLASS表示使用全限定类名作为类型值:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public abstract class Person {}

再次执行,可以看到序列化时,包含了一个对象的Class类型属性键值对,所以在反序列时使用指定类型的构造,正确输出:

{"personList":[{"@class":"com.pearl.jacksoncore.demo.databind.anno.Student","name":"坤坤童鞋"},{"@class":"com.pearl.jacksoncore.demo.databind.anno.Teacher","name":"悠上老师"}]}
com.pearl.jacksoncore.demo.databind.anno.PersonVO@32eff876

2.18 @JsonSubTypes

@JsonSubTypes用于指定用于多态类型时,指定子类的类型标识。

@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonSubTypes {Type[] value();boolean failOnRepeatedNames() default false;

下方示例中,@JsonTypeInfo表示使用type作为子类类型属性名,使用自定义名称作为子类类型值,@JsonSubTypes指定Student类的名称为stuTeacher类的名称为stu

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({@JsonSubTypes.Type(value = Student.class,name = "stu"),@JsonSubTypes.Type(value = Teacher.class,name = "tea")
})
public abstract class Person {//......}

序列化后输出如下:

{"personList":[{"type":"stu","name":"坤坤童鞋"},{"type":"tea","name":"悠上老师"}]}

2.19 @JsonTypeName

@JsonTypeName作用在类上,用于添加当前类的类型标识符,常用于配合@JsonTypeInfo多态类型处理问题。

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

Student类上添加注解:

@JsonTypeName("student111111")
public class Student extends Person{//......}

可以看到在序列化后携带了配置的类型标识:

{"personList":[{"student111111":{"name":"坤坤童鞋"}},{"teacher":{"name":"悠上老师"}}]}

2.20 @JsonTypeId

除了使用@JsonTypeName还可以使用@JsonTypeId添加类型标识,可以添加在属性、方法、参数上。

@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonTypeId {
}

示例代码:

public class Student extends Person{@JsonTypeIdprivate String typeId;// getters and setters     
}public class Student extends Person{@JsonTypeIdprivate String typeId;// getters and setters     
}```java
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({@JsonSubTypes.Type(value = Student.class,name = "sut11111111"),@JsonSubTypes.Type(value = Teacher.class,name = "tea1111111")
})

输出结果:

{"personList":[{"sut11111111":{"name":"坤坤童鞋"}},{"tea1111111":{"name":"悠上老师"}}]}

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

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

相关文章

QT 最近使用的项目配置文件

目录 1 QT 最近使用的项目配置文件所在路径 2 QtCreator.ini 1 QT 最近使用的项目配置文件所在路径 C:\Users\your username\AppData\Roaming\QtProject QtCreator.ini最好先备份一份 2 QtCreator.ini ProjectExplorer 下面的 RecentProjects\FileNames RecentProjects\…

Vue3:快速上手路由器

本人在B站上关于vue3的尚硅谷的课程&#xff0c;以下是整理一些笔记。 一.路由器和路由的概念 在 Vue 3 中&#xff0c;路由&#xff08;Router&#xff09;和路由器&#xff08;Router&#xff09;是两个相关但不同的概念。 1. 路由&#xff08;Router&#xff09;&#xff…

链表基础题

206. 反转链表 问题描述 给定单链表的头节点 head &#xff0c;请反转链表&#xff0c;并返回反转后的链表的头节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;…

Cocos Creator 常见问题记录

目录 问题1、精灵图九宫格&#xff0c;角度不拉伸 问题2、BlockInputEvents 防止透屏 问题1、精灵图九宫格&#xff0c;角度不拉伸 点击编辑&#xff0c;拖拽到可变区域 问题2、BlockInputEvents 防止透屏

三菱GX WORKS3连接FX5U系列PLC时,弹出窗口提示:用户认证功能或安全性强化模式未启用

三菱GX WORKS3连接FX5U系列PLC时&#xff0c;弹出窗口提示&#xff1a;用户认证功能或安全性强化模式未启用 如下图所示&#xff0c;使用GX WORKS3编程软件连接FX5U系列PLC&#xff0c; 首先&#xff0c;在连接目标中选择自己当前使用的网卡适配器&#xff0c;并将IP地址设置在…

预训练大模型最佳Llama开源社区中文版Llama2

Llama中文社区率先完成了国内首个真正意义上的中文版Llama2-13B大模型&#xff0c;从模型底层实现了Llama2中文能力的大幅优化和提升。毋庸置疑&#xff0c;中文版Llama2一经发布将开启国内大模型新时代。 作为AI领域最强大的开源大模型&#xff0c;Llama2基于2万亿token数据预…

【pytest】执行环境切换的两种解决方案

一、痛点分析 在实际企业的项目中&#xff0c;自动化测试的代码往往需要在不同的环境中进行切换&#xff0c;比如多套测试环境、预上线环境、UAT环境、线上环境等等&#xff0c;并且在DevOps理念中&#xff0c;往往自动化都会与Jenkins进行CI/CD&#xff0c;不论是定时执行策略…

Leetcode 剑指 Offer II 071.按权重随机选择

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定一个正整数数组 w &#xff0c;其中 w[i] 代表下标 i 的权重…

《AIGC重塑金融:AI大模型驱动的金融变革与实践》

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-oBSlqt4Vga1he7DL {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

聊聊k8s服务发现的优缺点

序 本文主要研究一下使用k8s服务发现的优缺点 spring cloud vs kubernetes 这里有张spring cloud与kubernetes的对比&#xff0c;如果将微服务部署到kubernetes上面&#xff0c;二者有不少功能是重复的&#xff0c;可否精简。 这里主要是讲述一下如果不使用独立的服务发现&am…

websocket 局域网 webrtc 一对一 视频通话的实例

基本介绍 使用websocket来 WebRTC 建立连接时的 数据的传递和交换。 WebRTC 建立连接时&#xff0c;通常需要按照以下顺序执行一些步骤&#xff1a; 1.创建本地 PeerConnection 对象&#xff1a;使用 RTCPeerConnection 构造函数创建本地的 PeerConnection 对象&#xff0c;该…

爬取b站音频和视频数据,未合成一个视频

一、首先找到含有音频和视频的url地址 打开一个视频&#xff0c;刷新后&#xff0c;找到这个包&#xff0c;里面有我们所需要的数据 访问这个数据包后&#xff0c;获取字符串数据&#xff0c;用正则提取&#xff0c;再转为json字符串方便提取。 二、获得标题和音频数据后&…

FreeRTOS day1

1.总结keil5下载代码和编译代码需要注意的事项 需要与板子连通 配置完成后才点击下载 2.总结STM32Cubemx的使用方法和需要注意的事项 下载支持包 打开芯片配置界面 3.总结STM32Cubemx配置GPIO的方法

【动手学深度学习-pytorch】9.2长短期记忆网络(LSTM)

长期以来&#xff0c;隐变量模型存在着长期信息保存和短期输入缺失的问题。 解决这一问题的最早方法之一是长短期存储器&#xff08;long short-term memory&#xff0c;LSTM&#xff09; (Hochreiter and Schmidhuber, 1997)。 它有许多与门控循环单元&#xff08; 9.1节&…

目标检测评价标准

主要借鉴&#xff1a;https://github.com/rafaelpadilla/Object-Detection-Metrics?tabreadme-ov-file 主要评价指标、术语&#xff1a; Intersection Over Union (IOU)&#xff1a;两个检测框交集面积与并集面积的比值 True Positive (TP)&#xff1a;IOU大于阈值的检测框…

uniapp实现列表动态添加

1.效果图&#xff1a; 2.代码实现&#xff1a; 这里没有用uniapp提供的uni-list控件 <template> <view id"app"> <!-- 这里为了让标题&#xff08;h&#xff09;居中展示&#xff0c;给h标签设置了父标签&#xff0c;并设置父标签text-…

物联网实战--入门篇之(四)嵌入式-UART驱动

目录 一、串口简介 二、串口驱动设计 三、串口发送 四、串口接收处理 五、PM2.5数据接收处理 六、printf重定义 七、总结 一、串口简介 串口在单片机的开发中属于非常常用的外设&#xff0c;最基本的都会预留一个调试串口用来输出调试信息&#xff0c;串口时序这里就不谈…

既有理论深度又有技术细节——深度学习计算机视觉

推荐序 我曾经试图找到一本既有理论深度、知识广度&#xff0c;又有技术细节、数学原理的关于深度学习的书籍&#xff0c;供自己学习&#xff0c;也推荐给我的学生学习。虽浏览文献无数&#xff0c;但一直没有心仪的目标。两周前&#xff0c;刘升容女士将她的译作《深度学习计…

java中的单例模式

一、描述 单例模式就是程序中一个类只能有一个对象实例 举个例子: //引出单例模式&#xff0c;一个类中只能由一个对象实例 public class Singleton1 {private static Singleton1 instance new Singleton1();//通过这个方法来获取实例public static Singleton1 getInstance…

Verilog语法回顾--门级和开关级模型

目录 门和开关的声明 门和开关类型 支持驱动强度的门 延迟 实例数组 and&#xff0c;nand&#xff0c;nor&#xff0c;or&#xff0c;xor&#xff0c;xnor buf&#xff0c;not bufif1&#xff0c;bufif0&#xff0c;notif1&#xff0c;notif0 MOS switches Bidirecti…