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

news2024/9/22 17:18:46

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

本系列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

    @JsonValue
    private 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中的键:

    @JsonKey
    private 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<>();

    @JsonAnySetter
    public 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

    @JsonAnyGetter
    public 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指定属性映射关系:

    @JsonCreator
    public 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;
	// 确定在其子类型的多态反序列化过程中是否应严格要求类型ID
    OptBoolean 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 information
 at [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{

    @JsonTypeId
    private String typeId;
  // getters and setters     
}

public class Student extends Person{

    @JsonTypeId
    private 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.coloradmin.cn/o/1552655.html

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

相关文章

增强现实(AR)和虚拟现实(VR)营销的未来:沉浸式体验和品牌参与

--- 如何将AR和VR技术应用于营销&#xff0c;以提高品牌知名度、客户参与度 增强现实&#xff08;AR&#xff09;和虚拟现实&#xff08;VR&#xff09;不再只是游戏。这些技术为品牌与受众互动提供了创新的方式。营销人员可以创造更好的客户体验&#xff0c;并为身临其境的故…

Docker进阶:使用Docker部署Harbor私有镜像仓库

Docker进阶&#xff1a;使用Docker部署Harbor私有镜像仓库 1、安装Docker和Docker Compose1、安装Docker、Docker Compose2、验证Docker和Docker Compose是否成功安装3、先启动运行docker服务 2、下载并配置Harbor1、下载最新版本的Harbor离线安装包2、配置Harbor的主机名和管理…

Java毕业设计-基于springboot开发的休闲娱乐代理售票系统-毕业论文+答辩PPT(附源代码+演示视频)

文章目录 前言一、毕设成果演示&#xff08;源代码在文末&#xff09;二、毕设摘要展示1、开发说明2、需求分析3、系统功能结构 三、系统实现展示1、系统功能模块2、后台登录2.1管理员功能2.2用户功能 四、毕设内容和源代码获取总结 Java毕业设计-基于springboot开发的休闲娱乐…

linux中查看内存占用空间

文章目录 linux中查看内存占用空间 linux中查看内存占用空间 使用 df -h 查看磁盘空间 使用 du -sh * 查看每个目录的大小 注意这里是当前目录下的文件大小&#xff0c;查看系统的可以回到根目录 经过查看没有发现任何大的文件夹。 继续下面的步骤 如果您的Linux磁盘已满&a…

对话 Mines of Dalarnia: Web3 游戏创新,社区驱动与公链共建

作者&#xff1a;stellafootprint.network 嘉宾&#xff1a;Manfred Pack&#xff0c;Mines of Dalarnia 游戏开发总监 采访者&#xff1a;Alex Cooper&#xff0c;Footprint Analytics 北美社区与 BD 负责人 在区块链游戏领域&#xff0c;去中心化和玩家经济正在颠覆传统游戏…

利用机器学习打造反电信诈骗系统

利用机器学习打造反电信诈骗系统 技术与功能数据集与模型可视化分析与词云结语 随着互联网的普及&#xff0c;电信诈骗日益猖獗&#xff0c;给人们的生活和财产安全带来了巨大的威胁。为了有效应对这一挑战&#xff0c;我们开发了一款基于机器学习的反电信诈骗系统&#xff0c;…

opencv 十九 python下实现多线程间rtsp直播流的复用

在多线程拉流的任务场景中&#xff0c;有时需要将一个rtsp拉取多次&#xff0c;每重新打开一次rtsp视频流就要多消耗一次带宽&#xff0c;为此基于类的静态对象实现rtsp视频流的复用。 1、实现代码 import threading import cv2,time #接收摄影机串流影像&#xff0c;采用多线…

Haproxy2.8.1+Lua5.1.4部署,haproxy.cfg配置文件详解和演示

目录 一.快速安装lua和haproxy 二.配置haproxy的配置文件 三.配置haproxy的全局日志 四.测试负载均衡、监控和日志效果 五.server常用可选项 1.check 2.weight 3.backup 4.disabled 5.redirect prefix和redir 6.maxconn 六.调度算法 1.静态 2.动态 一.快速安装lu…

C语言:动态内存管理(上)

目录 前言 1、动态内存函数的介绍 1.1 malloc和free 1.2 calloc函数​编辑 结语 前言 在我们之前对于c语言的学习中&#xff0c;我们知道&#xff0c;当我们要存放数据时&#xff0c;可以定义相应的变量取存放&#xff0c;但是在变量定义后&#xff0c;其大小是无法改变的…

Unbtun-arach64架构安装PySide2(python3.6)

aarch平台是无法通过pip安装PySide2的&#xff0c;同时利用源码下载一直报错 1. 我是python3.6.9&#xff0c;在官网上找到对应的PySide2版本 5.15.2.所以首先在官网下载Qt5.15.2的源码&#xff1a;https://download.qt.io/archive/qt/5.15/5.15.2/single/ 2. 编译qt环境 aar…

网站为什么要选择使用安全加速SCDN?

安全加速SCDN&#xff08;安全内容交付网络&#xff09;是一种网络加速服务&#xff0c;旨在提高网站和应用程序的性能和安全性。它使用专门的技术和基础设施来加速内容传输并保护网站免受网络攻击。 安全加速SCDN可以通过内容缓存、快速传输和动态路由技术来加速网站和应用程…

【二叉树】Leetcode 98. 验证二叉搜索树【中等】

验证二叉搜索树 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例1&a…

理想汽车推出首个全自研大模型Mind GPT,通过国家备案正式上线

理想汽车在今日宣布&#xff0c;其全自研的多模态认知大模型——Mind GPT&#xff0c;已正式通过国家《生成式人工智能服务管理暂行办法》的备案&#xff0c;并成功上线&#xff0c;标志着理想成为首个拥有自研大模型并通过国家备案的汽车厂商。 理想Mind GPT是汽车行业首个专门…

Python图像处理——计算机视觉中常用的图像预处理

概述 在计算机视觉项目中&#xff0c;使用样本时经常会遇到图像样本不统一的问题&#xff0c;比如图像质量&#xff0c;并非所有的图像都具有相同的质量水平。在开始训练模型或运行算法之前&#xff0c;通常需要对图像进行预处理&#xff0c;以确保获得最佳的结果。图像预处理…

MySQL索引18连问,谁能顶住

前言 过完这个节&#xff0c;就要进入金银季&#xff0c;准备了 18 道 MySQL 索引题&#xff0c;一定用得上。 作者&#xff1a;感谢每一个支持&#xff1a; github 1. 索引是什么 索引是一种数据结构&#xff0c;用来帮助提升查询和检索数据速度。可以理解为一本书的目录&…

linux离线安装jenkins及使用教程

本教程采用jenkins.war的方式离线安装部署&#xff0c;在线下载的方式会遇到诸多问题&#xff0c;不宜采用 一、下载地址 地址&#xff1a;Jenkins download and deployment 下载最新的长期支持版 由于jenkins使用java开发的&#xff0c;所以需要安装的linux服务器装有jdk环…

centos node puppeteer chrome报错问题

原因&#xff1a;缺少谷歌依赖包&#xff0c;安装以下即可 yum install atkyum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf…

uni-app(使用阿里图标)

1.注册阿里矢量图标库 注册阿里图标库账号并登录&#xff0c;https://www.iconfont.cn/ 2.加入购物车 搜索适合自己的图标&#xff0c;加入购物车&#xff0c;如下图&#xff1a; 3.加入项目 我的->资源管理->我的项目->创建项目&#xff0c;然后返回购物车&#…

【电路笔记】-交流电路波形的形状因子

波形的形状因子 文章目录 波形的形状因子1、概述2、正弦波波形因子3、波形因子示例14、波形因子示例25、单相半波整流波形6、单相全波整流波形7、三角波形形状因子8、锯齿波形因子9、方波和脉冲波形10、总结波形因子描述波形的形状或结构,是其均方根值与其平均值的比率。 1、概…

ZK友好代数哈希函数安全倡议

1. 引言 前序博客&#xff1a; ZKP中的哈希函数如何选择ZK-friendly 哈希函数&#xff1f;snark/stark-friendly hash函数Anemoi Permutation和Jive Compression模式&#xff1a;高效的ZK友好的哈希函数Tip5&#xff1a;针对Recursive STARK的哈希函数 随着Incrementally Ve…