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.mzph.cn/news/788160.shtml

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

相关文章

WebKit揭秘:从内部结构到应用程序开发

文章目录 WebKit结构简介核心模块其他组件多进程架构&#xff08;WebKit2&#xff09; Wekbit做了什么&#xff1f;应用程序如何利用 Webkit WebKit结构简介 WebKit是一个开源的浏览器引擎&#xff0c;它由多个模块组成&#xff0c;这些模块协同工作以提供Web内容的渲染和交互…

英伟达智算先锋训练,冲刺智算时代实战

随着数字经济的深入发展&#xff0c;智能算力作为关键生产力&#xff0c;其规模在2022年已达到268.0 EFLOPS&#xff0c;并预计到2028年将增长至2769 EFLOPS&#xff0c;显示出强劲的发展势头。在2024年政府工作报告中&#xff0c;也首次提出了“人工智能”行动&#xff0c;强调…

Python轻量级框架Flask开发web应用(附源码自取)

目录 介绍 安装 简单初使用 新建项目目录 视图映射 无参映射 带参映射 ? 传参映射 连接mysql orm对象视图映射建表 ​编辑 crud操作 新增操作 查询操作 普通查询 查询返回json数据 前端传递json体数据查询 更新操作 删除操作 orm表关系映射 flask-migrate迁…

【Vue】vue3简介与环境配置

文章目录 项目编码规范什么是 Vue&#xff1f;安装node环境nvm针对node版本惊醒管理的工具 项目编码规范 组合式API Typescript setup(语法糖) 什么是 Vue&#xff1f; Vue 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;…

JavaBean是什么?

Bean的本意为豌豆、子实&#xff0c;在这里引申为一种实体。JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean&#xff0c;类必须是具体的和公共的&#xff0c;并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性&#xff0…

【总结】在嵌入式设备上可以离线运行的LLM--Llama

文章目录 Llama 简介运用另一种&#xff1a;MLC-LLM 一个令人沮丧的结论在资源受限的嵌入式设备上无法运行LLM&#xff08;大语言模型&#xff09;。 一丝曙光&#xff1a;tinyLlama-1.1b&#xff08;10亿参数&#xff0c;需要至少2.98GB的RAM&#xff09; Llama 简介 LLaMA…

电商技术揭秘四:电商平台的物流管理系统

文章目录 引言一、物流管理系统的功能与架构1.1 物流管理系统在电商平台中的作用概述保障订单的及时配送优化库存管理控制运营成本提升客户服务水平支持数据驱动的决策应对市场变化 1.2 订单处理功能分析自动化处理流程订单分配与履行错误检测与处理机制实时订单状态更新订单数…

ZKP价值链路的垂直整合

1. ZKP proof生命周期 从ZKP&#xff08;zero-knowledge proof&#xff09;生命周期&#xff0c;先看围绕ZKP的价值链路形成&#xff1a; 1&#xff09;User intent用户意图&#xff1a;以某用户意图为起点&#xff0c;如想要在某zk-rollup上swap某token、证明其身份、执行某…

【从零开始】自建高质量免费ip代理池(截止2024.4.1最新版)

文章目录 前言基础常识代理服务器状态码端口号 常见免费ip代理池网站实现思路代码实现main.pyutils.pydemo.py 结果如下 前言 为了防止ip被封后还能爬取网页&#xff0c;最常见的方法就是自己构建一个ip代理池。 本来用的是下面这个开源项目ip代理池&#xff0c; github开源项…

二维数字滤波器设计

Rafael C. Gonzalez “Digital Image Processing”的错误 按理说这本书的第三作者Steven是数字信号处理出身&#xff0c;他本人又对信号处理非常熟悉&#xff0c;不能理解为什么这本书的频域滤波器一章几乎没有对的地方。 对于巴特沃斯等模拟滤波器&#xff0c;利用全通带减去…

GPT 模型解析:ChatGPT 如何在语言处理领域引领潮流?

人工智能时代来临 我们正处于AI的iPhone时刻。——黄仁勋&#xff08;英伟达CEO&#xff09; ChatGPT 好得有点可怕了&#xff0c;我们距离危险的强人工智能不远了。——马斯克&#xff08;Tesla/SpaceX/Twitter CEO&#xff09; 以上的内容说明我们现在正处于一个技术大翻牌的…

就业班 第二阶段 2401--3.29 day9 shell之正则+数组

九、shell 编程-数组 普通数组:只能用整数作为数组的索引 关联数组:可以使用字符串作为数组的索引 数组定义 普通数组定义: [rootnewrain shell]# books( linux shell awk sed ) 引用: [rootnewrain shell]# echo ${books[0]} linux [rootnewrain shell]# echo ${books[1]…

篮球竞赛预约平台的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)篮球馆,篮球赛,竞赛项目,赛事预约

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读300套最新项目持续更新中..... 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含ja…

苍穹外卖06(HttpClient,微信小程序开发,微信登录流程,获取授权码从微信平台获取用户信息)

目录 一、HttpClient 1. 介绍 2. 入门案例 1 导入依赖(已有) 2 GET方式请求 2 POST方式请求 二、微信小程序开发 1. 介绍 2. 准备工作 1 注册小程序获取AppID 注册小程序 完善小程序信息 2 下载并安装开发者工具 3 设置小程序开发者工具(必做) 3. 入门案例 1 小…

Screeps Arena 游戏基础教程

一. 游戏内教程汉化1. 循环和导入&#xff08;Loop and Import&#xff09;2. 简单移动&#xff08;Simple move&#xff09;3. 首次攻击&#xff08;First Attack&#xff09;4. 爬虫的身体部分&#xff08;Creeps Bodies&#xff09;5. 存储和转移 &#xff08;Store and Tra…

通过提交容器的方式修改ubuntu镜像的apt源

通过提交容器的方式修改ubuntu镜像的apt源 步骤总结 问题&#xff0c;每次创建容器之后&#xff0c;都要在容器内手动更改镜像源。 不如&#xff0c;干脆修改镜像的apt源&#xff0c;一次到位。 步骤 先创建一个容器&#xff0c;到容器内执行变更命令。 D:/sandbox> dock…

Yarn 的安装和使用

在前端开发中&#xff0c;包管理工具是必不可少的利器&#xff0c;而 Yarn 就是其中一个备受欢迎的选择。本文将介绍如何安装和使用 Yarn&#xff0c;并解决可能遇到的一些常见问题&#xff0c;让你更高效地管理项目依赖。 什么是 Yarn&#xff1f; Yarn 是由 Facebook、Goo…

算法学习——LeetCode力扣图论篇1(797. 所有可能的路径、200. 岛屿数量、695. 岛屿的最大面积)

算法学习——LeetCode力扣图论篇1 797. 所有可能的路径 797. 所有可能的路径 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个有 n 个节点的 有向无环图&#xff08;DAG&#xff09;&#xff0c;请你找出所有从节点 0 到节点 n-1 的路径并输出&#xff08;不要求按特…

【单】Unity _RPG项目中的问题

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a; ⭐…

C++:多态、模板

一、多态 相同的代码、实现不同的功能 1.前提 1.类之间有继承关系 2.父类中有虚函数 3.父类的指针指向子类的对象 2.函数重写 1.发生在继承之间 2.父类中有虚函数 3.子类中对父类的虚函数重新实现 3.虚函数 1.在函数头前加上virtual 2.只要基类中的函数是虚函数&#xff0c;后…