Jackson 2.x 系列【20】混合注解 Mixin Annotations

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

本系列Jackson 版本 2.17.0

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

文章目录

    • 1. 需求场景
    • 2. 混合注解
      • 2.1 创建混合类
      • 2.2 关联
      • 2.3 测试
    • 3. @JsonMixin

1. 需求场景

在某个疯狂星期四的下午,小坤👱正在啃着腿,偷偷刷着电脑版某音💃💃💃,突然经理的👴从旁边凑了过来,并道:这(人人)不错…

小坤👱:经经经…理

经理👴:没事,都是爷们儿,我懂…这里有个需求你做下

经理👴:认证项目中引入了一个第三包,登录时调用包中的认证方法返回令牌对象TokenInfo,我们将令牌序列化后返回给前端

经理👴:令牌对象中的usernamepassword属性添加了@JsonIgnore注解,在序列化时会被忽略,birthday属性格式为yyyy-MM-dd HH:mm:ss::

public class TokenInfo {@JsonIgnoreString username;@JsonIgnoreString password;@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")Date birthday;// 省略......
}

经理👴:现在要求序列化时username不能被忽略,birthday的格式只需要具体到年月日

小坤👱:没问题,经理,交给我吧!

小坤👱看了看代码,稍作思考,这…还不简单吗…既然第三方包的对象无法修改,那我先定义一个VO,使用注解指定序列化规则:

public class TokenInfoVO {String username;@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")Date birthday;// 省略......
}

然后将令牌对象转换为VO再执行序列化:

        ObjectMapper objectMapper = new ObjectMapper();// 模拟第三包返回令牌对象TokenInfo tokenInfo=new TokenInfo();tokenInfo.setUsername("王法");tokenInfo.setBirthday(new Date());tokenInfo.setPassword("123456");// 转换为对应格式的VOTokenInfoVO vo=new TokenInfoVO();vo.setUsername(tokenInfo.getUsername());vo.setBirthday(tokenInfo.getBirthday());// 序列化String value = objectMapper.writeValueAsString(vo);System.out.println(value);// 

几分钟不到,小坤👱就已完成了需求,并满脸欢喜的在群里@了经理:李总,刚才的需求已经做完了。

小坤👱内心OS:怎么样,傻眼了吧,没想到吧,我这么快就做完了,厉害吧!!有我这里牛逼的开发,你就偷着乐吧你!!!

小坤👱紧紧盯着屏幕,期待这经理会在群里表扬几句…

可是没想到经理👴回话:小坤,你这是写的什么阿!!!有考虑过代码的可维护性、可扩展性、简洁性吗?明明一行代码就能搞定的问题,你这是写的屎山吗???

小坤👱刚浮起的笑意顿时僵住了:犊子,这是在玩我吧,不能修改第三方类,又要添加基于注解的序列化规则,还特么能有其他的处理方式?

2. 混合注解

Mixin翻译为:混合类型;米心;混进;糅合;

Jackson提供了一种混合注解机制(mix-in annotations),允许开发者在不修改原始类的情况下,为其添加或覆盖特定的注解。

2.1 创建混合类

创建一个混合类,将需要重新处理的属性复制过来,并添加需要的注解,例如username设置为不忽略,birthday指定新的格式化模板:

public abstract class MixinTokenInfo {@JsonIgnore(value = false)String username;@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")Date birthday;
}

2.2 关联

混合类原始类关联起来,就可以动态地改变原始类的序列化或反序列化行为。

ObjectMapper 提供了关联方法:

    /*** 向指定的类或接口添加混合注解,以扩充其功能** @param target 被覆盖的类(或接口)* @param mixinSource 混合类* @since 2.5*/public ObjectMapper addMixIn(Class<?> target, Class<?> mixinSource){_mixIns.addLocalDefinition(target, mixinSource);return this;}

示例代码:

        // 关联objectMapper.addMixIn(TokenInfo.class,MixinTokenInfo.class);

2.3 测试

最终代码如下所示:

        ObjectMapper objectMapper = new ObjectMapper();// 关联objectMapper.addMixIn(TokenInfo.class,MixinTokenInfo.class);// 模拟第三包返回令牌对象TokenInfo tokenInfo=new TokenInfo();tokenInfo.setUsername("王法");tokenInfo.setBirthday(new Date());tokenInfo.setPassword("123456");// 序列化String value = objectMapper.writeValueAsString(tokenInfo);System.out.println(value);

查看输出结果:

{"username":"王法","birthday":"2024-04-10"}

3. @JsonMixin

Spring Boot默认使用Jackson作为JSON框架,例如自动配置中已经帮我们注册了一个ObjectMapper

		@Bean@Primary // 主要的@ConditionalOnMissingBean // 在应用程序没有注册ObjectMapper时生效ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {return builder.createXmlMapper(false).build();}

在进行JSON操作时,直接注入ObjectMapper即可:

    @AutowiredObjectMapper objectMapper;

也提供了相应的扩展,比如Spring Boot 2.7版本提供了@JsonMixin,启动时会扫描加载被@JsonMixin标识的类,不需要再显式的调用addMixIn方法声明关联关系,使用起来更加的方便。

@JsonMixin注解源码如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface JsonMixin {@AliasFor("type")Class<?>[] value() default {};@AliasFor("value")Class<?>[] type() default {};
}

Spring Boot工程中,混合类添加@JsonMixin注解,并指定原始类

@JsonMixin(TokenInfo.class) // 需要修改的目标类
public abstract class MixinTokenInfo {@JsonIgnore(value = false)String username;@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")Date birthday;
}

单元测试:

    @AutowiredObjectMapper objectMapper;@Testvoid testMixIn() throws JsonProcessingException {// 模拟第三包返回令牌对象TokenInfo tokenInfo=new TokenInfo();tokenInfo.setUsername("王法");tokenInfo.setBirthday(new Date());tokenInfo.setPassword("123456");// 序列化String value = objectMapper.writeValueAsString(tokenInfo);System.out.println(value);}

查看输出结果:

{"username":"王法","birthday":"2024-04-11"}

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

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

相关文章

RabbitMQ-核心特性

已经不需要为RabbitMQ交换机的离去而感到伤心了&#xff0c;接下来登场的是RabbitMQ-核心特性!!! 文章目录 核心特性消息过期机制消息确认机制死信队列 核心特性 消息过期机制 官方文档&#xff1a;https://www.rabbitmq.com/ttl.html 可以给每条消息指定一个有效期&#xf…

Ubuntu 20.04.06 PCL C++学习记录(二十五)

[TOC]PCL中点云分割模块的学习 学习背景 参考书籍&#xff1a;《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,&#xff0c;PCL版本为1.10.0&#xff0c;CMake版本为3.16&#xff0c;可用点云下载地址 学习内容 使用渐进形态滤波器分割识别地面回波&#xff0c;即执…

【一竞技CS2】VP战队官宣签下electroNic取代mir

1、近日VP战队官宣签下electroNic&#xff0c;以取代阵容中的mir。 electroNic自己也表示&#xff1a;“VP是一支顶级队伍。阵容核心曾赢得Major冠军&#xff0c;所有队员都处于巅峰状态并且时刻准备着去争夺冠军。我们有着一样的雄心壮志。 此外我还对和Jame很感兴趣&#xf…

日历签到功能实现

日历签到功能实现&#xff1a;前后端全面详细指南 在本文中&#xff0c;我们将详细介绍如何使用Vue&#xff08;前端&#xff09;和SpringBoot&#xff08;后端&#xff09;搭配Vant组件库来实现一个日历签到功能。这个功能将允许用户在日历上进行每日签到&#xff0c;并跟踪他…

C++从入门到精通——const与取地址重载

const与取地址重载 前言一、const正常用法const成员函数问题const对象可以调用非const成员函数吗非const对象可以调用const成员函数吗const成员函数内可以调用其它的非const成员函数吗非const成员函数内可以调用其它的const成员函数吗总结 二、取地址及const取地址操作符重载概…

如何用Jenkins执行自动化测试构建

摘要 依据Jenkins官网介绍&#xff0c;Jenkins是一个流行的开源持续集成和交付工具&#xff0c;它提供了一个可扩展的插件生态系统&#xff0c;可以用于自动化构建、测试和部署软件项目。 本文介绍如何安装使用Jenkins、常见问题解决方案以及深入应用&#xff0c;为自动化测试…

艾迪比皮具携手工博科技SAP ERP公有云,打造数字化转型新标杆

4月1日&#xff0c;广州市艾迪比皮具有限公司&#xff08;以下简称“艾迪比”&#xff09;SAP S/4HANA Cloud Public Edition&#xff08;以下简称“SAP ERP公有云”&#xff09;项目正式启动。双方项目组领导、成员出席本次项目启动会&#xff0c;为未来项目的顺利实施打下坚实…

Python编程实训平台(1)

Python编程实训平台是一套建立在虚拟化层上基于Python的编程环境&#xff0c;用于开展大数据相关实训课程教学和课后训练的平台。该平台内部包含Python运行环境&#xff0c;用户无需受限于本身的电脑配置&#xff0c;可以直接从教学管理平台进入平台进行Python编程。 一、功能…

滚雪球学Java(74):深入理解JavaSE输入输出流:掌握数据流动的奥秘

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴 bug菌&#xff0c;今天又来给大家手把手教学Java SE系列知识点啦&#xff0c;赶紧出来哇&#xff0c;别躲起来啊&#xff0c;听我讲干货记得点点赞&#xff0c;赞多了我就更有动力讲得更欢哦&#xff01;所以呀&…

nginx学习记录-动静分离

1. 动静分离原理 我们在访问网站资源的时候&#xff0c;通常会将资源分成两种&#xff0c;一种是静态资源&#xff08;前端的固定界面&#xff0c;比如图片&#xff0c;html页面等&#xff09;&#xff0c;这些资源无需后台程序处理&#xff1b;另一种是动态资源&#xff0c;这…

分布式调度器

xxl-job介绍 xxl-job 是一个轻量级分布式任务调度框架&#xff0c;支持动态添加、修改、删除定时任务&#xff0c;支持海量任务分片执行&#xff0c;支持任务执行日志在线查看和分页查询&#xff0c;同时支持任务失败告警和重试机制&#xff0c;支持分布式部署和高可用。xxl-j…

阿里云、腾讯云、华为云优惠券领取入口整理汇总

阿里云、腾讯云、华为云作为国内领先的云服务提供商&#xff0c;一直以其稳定、高效、安全的服务赢得了广大用户的青睐。为了回馈用户&#xff0c;这些云平台经常会推出各种优惠活动&#xff0c;其中最为常见的便是优惠券。本文将为大家整理汇总阿里云、腾讯云、华为云优惠券的…

linux-centos虚拟机设置固定ip

环境准备 虚拟机版本&#xff1a;centos7 安装环境&#xff1a;vmware17 1、设置网络连接 虚拟机-设置-网络适配器-NAT模式 2、查看子网信息 编辑-虚拟网络编辑器-NAT模式-NAT设置 查看子网ip和网关ip 下一步要用 3、修改配置文件 vim /etc/sysconfig/network-scripts…

构建数据平台架构指导原则与平台核心组件说明

文章目录 前言什么是数据架构&#xff1f;数据架构如何帮助构建数据平台&#xff1f;数据平台核心组件数据源系统数据加载数据存储数据处理和转换提供使用数据的方式公共服务 前言 湖仓一体是最近几年非常流行的现代大数据架构&#xff0c;目前它已经成为设计数据平台架构的首…

代码随想录算法训练营第四十三天|1049.最后一块石头的重量 II、494. 目标和、474.一和零

动态规划 文章目录 一、最后一块石头的重量二、目标和三、一和零总结 一、最后一块石头的重量 此题的关键在于转化思路&#xff0c;要求剩下最少的石块&#xff0c;也就是两堆相差不多的石块相互碰撞&#xff0c;所以求其中的一堆能够达到的最大数量&#xff0c;另外一堆也就随…

Flask框架初探-如何在本机发布一个web服务并通过requests访问自己发布的服务-简易入门版

Flask框架初探 在接触到网络框架之前我其实一直对一个事情有疑惑&#xff0c;跨语言的API在需要传参的情况下究竟应该如何调用&#xff0c;之前做过的项目里&#xff0c;我用python做了一个代码使用一个算法得到一个结果之后我应该怎么给到做前端的同学或者同事&#xff0c;之前…

基于springboot 的医院信管系统

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

YOLOv5参数大全(parse_opt篇)

文章目录 1、前言2、train.py-文件解读2.1、常用的参数2.1.1、weights2.1.2、cfg2.1.3、data2.1.4、epochs2.1.5、batch-size2.1.6、imgsz2.1.7、device2.1.8、resume2.1.9、hyp2.1.10、adam 3、detect.py-文件解读3.1、常用的参数3.1.1、weights3.1.2、source3.1.3、imgsz3.1.…

麦克风性能参数

1.声压级&#xff08;Sound Pressure Level&#xff09; 一个用来衡量声音压力的参数&#xff0c;基本上描述的是声音的强度、大小或响度&#xff0c;单位通常为分贝&#xff08;dB&#xff09;。声压级是相对于参考声压来定义的。在空气中&#xff0c;参考声压通常是20微帕斯卡…

SpringBoot新增菜品模块开发(事务管理+批量插入+主键回填)

需求分析与设计 一&#xff1a;产品原型 后台系统中可以管理菜品信息&#xff0c;通过 新增功能来添加一个新的菜品&#xff0c;在添加菜品时需要选择当前菜品所属的菜品分类&#xff0c;并且需要上传菜品图片。 新增菜品原型&#xff1a; 当填写完表单信息, 点击"保存…