Jackson 2.x 系列【24】Spring Web 集成之 Jackson2ObjectMapperBuilder

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

本系列Jackson 版本 2.17.0

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

文章目录

    • 1. 前言
    • 2. Spring Web
    • 3. Jackson2ObjectMapperBuilder
      • 3.1 成员属性
      • 3.2 静态方法
      • 3.3 自定义序列化/反序列化器
      • 3.4 模块注册
      • 3.5 启用/禁用特征
      • 3.6 混合注解
      • 3.7 构建
      • 3.8 配置
      • 3.9 其他

1. 前言

Spring生态使用Jackson作为默认的JSON处理框架,这些年随着Spring的大发异彩和Jackson本身的优越特性,已成为世界上最流行的JSON库。

接下来,本系列会讲解Spring MVCSpring Boot中如何使用Jackson,以及Spring对其进行扩展增强的相关源码,所以需要读者有一定的SpringSpring Boot开发经验。

2. Spring Web

Spring MVC对于后端开发人员来说已经很熟悉了,它是一个构建在Servlet之上的一个Web框架,而Spring WebSpring MVC的基础模块(还有一个Spring Flux ),它们同属于spring-framework框架。

Web框架在处理HTTP请求响应时,需要将请求报文反序列化为Java对象进行接收处理,在响应阶段,需要将Java对象反序列化为报文写出,所以需要依赖JSON框架去处理。

Spring Web中可以看到引入了JacksonGJson

在这里插入图片描述
spring-web模块的org.springframework.http.converter.json包下,可以看到Json集成的代码:

在这里插入图片描述

集成Jackson的主要有:

  • Jackson2ObjectMapperBuilderObjectMapper构建器
  • Jackson2ObjectMapperFactoryBean:创建和管理ObjectMapper Bean对象
  • MappingJackson2HttpMessageConverter:基于Jackson的消息转换器
  • SpringHandlerInstantiatorSpring环境集成
  • JacksonModulesRuntimeHintsSpring AOT所需的RuntimeHints(运行时提示)

3. Jackson2ObjectMapperBuilder

Jackson2ObjectMapperBuilder从名字上看已经很好理解,它是一个JacksonObjectMapper构建器,提供了Fluent API来定制ObjectMapper的默认属性并构建实例。

在之前我们都是通过new的方式创建ObjectMapper实例,现在可以使用构建者模式,这也是Spring自身使用和推荐使用的方式。

3.1 成员属性

	// 是否引入了`jackson-dataformat-xml`模块private static final boolean jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", Jackson2ObjectMapperBuilder.class.getClassLoader());// 混合注解类private final Map<Class<?>, Class<?>> mixIns = new LinkedHashMap<>();// 序列化器private final Map<Class<?>, JsonSerializer<?>> serializers = new LinkedHashMap<>();// 反序列化器private final Map<Class<?>, JsonDeserializer<?>> deserializers = new LinkedHashMap<>();private final Map<PropertyAccessor, JsonAutoDetect.Visibility> visibilities = new LinkedHashMap<>();// 特征private final Map<Object, Boolean> features = new LinkedHashMap<>();// 是否创建`XmlMapper`private boolean createXmlMapper = false;// 模块@Nullableprivate List<Module> modules;// JsonFactory@Nullableprivate JsonFactory factory;// 省略.........

3.2 静态方法

它的构造方法是public的,说明可以直接new创建Jackson2ObjectMapperBuilder

    public Jackson2ObjectMapperBuilder() {}

提供了多个创建不同数据类型支持的静态方法:

	// 构建 Jackson2ObjectMapperBuilderpublic static Jackson2ObjectMapperBuilder json() {return new Jackson2ObjectMapperBuilder();}// 构建 Jackson2ObjectMapperBuilder,并设置需要创建 XmlMapper,需要引入`jackson-dataformat-xml`模块,用于支持`XML`数据格式public static Jackson2ObjectMapperBuilder xml() {return new Jackson2ObjectMapperBuilder().createXmlMapper(true);}// 指定 JsonFactory-》SmileFactory,需要引入`jackson-dataformat-smile`模块,用于支持`Smile`数据格式public static Jackson2ObjectMapperBuilder smile() {return new Jackson2ObjectMapperBuilder().factory(new SmileFactoryInitializer().create());}// 指定 JsonFactory-》CBORFactory-》需要引入`jackson-dataformat-cbor`模块,用于支持`CBOR`数据格式public static Jackson2ObjectMapperBuilder cbor() {return new Jackson2ObjectMapperBuilder().factory(new CborFactoryInitializer().create());}

一般场景中,使用json()创建即可:

ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();

3.3 自定义序列化/反序列化器

提供了多个方法用于配置自定义序列化/反序列化器,相较于ObjectMapper不能直接添加来说,方便了很多。

	// 配置自定义序列化器(多个)public Jackson2ObjectMapperBuilder serializers(JsonSerializer<?>... serializers) {for (JsonSerializer<?> serializer : serializers) {Class<?> handledType = serializer.handledType();if (handledType == null || handledType == Object.class) {throw new IllegalArgumentException("Unknown handled type in " + serializer.getClass().getName());}this.serializers.put(serializer.handledType(), serializer);}return this;}// 为给定的类型配置自定义的序列化器(单个)public Jackson2ObjectMapperBuilder serializerByType(Class<?> type, JsonSerializer<?> serializer) {this.serializers.put(type, serializer);return this;}// 通过Map给定的类型配置自定义的序列化器(多个)public Jackson2ObjectMapperBuilder serializersByType(Map<Class<?>, JsonSerializer<?>> serializers) {this.serializers.putAll(serializers);return this;}// 添加自定义反序列化器public Jackson2ObjectMapperBuilder deserializers(JsonDeserializer<?>... deserializers) {// 省略.......return this;}// 省略其他类似.......

3.4 模块注册

提供了多个方法用于进行模块注册:

	public Jackson2ObjectMapperBuilder modules(Module... modules) {return modules(Arrays.asList(modules));}public Jackson2ObjectMapperBuilder modules(List<Module> modules) {// 省略......return this;}public Jackson2ObjectMapperBuilder modules(Consumer<List<Module>> consumer) {// 省略......return this;}public Jackson2ObjectMapperBuilder modulesToInstall(Module... modules) {// 省略......return this;}// 省略其他类似......

3.5 启用/禁用特征

提供了启用、禁用特征的相关方法:

	/*** 启用特征** @see com.fasterxml.jackson.core.JsonParser.Feature* @see com.fasterxml.jackson.core.JsonGenerator.Feature* @see com.fasterxml.jackson.databind.SerializationFeature* @see com.fasterxml.jackson.databind.DeserializationFeature* @see com.fasterxml.jackson.databind.MapperFeature*/public Jackson2ObjectMapperBuilder featuresToEnable(Object... featuresToEnable) {for (Object feature : featuresToEnable) {this.features.put(feature, Boolean.TRUE);}return this;}/*** 禁用特征** @see com.fasterxml.jackson.core.JsonParser.Feature* @see com.fasterxml.jackson.core.JsonGenerator.Feature* @see com.fasterxml.jackson.databind.SerializationFeature* @see com.fasterxml.jackson.databind.DeserializationFeature* @see com.fasterxml.jackson.databind.MapperFeature*/public Jackson2ObjectMapperBuilder featuresToDisable(Object... featuresToDisable) {for (Object feature : featuresToDisable) {this.features.put(feature, Boolean.FALSE);}return this;}

提供了直接配置一些特殊特征的开启/禁用方法:

	// MapperFeature#AUTO_DETECT_FIELDSpublic Jackson2ObjectMapperBuilder autoDetectFields(boolean autoDetectFields) {this.features.put(MapperFeature.AUTO_DETECT_FIELDS, autoDetectFields);return this;}// MapperFeature.AUTO_DETECT_GETTERS// MapperFeature.AUTO_DETECT_SETTERS// MapperFeature.AUTO_DETECT_IS_GETTERSpublic Jackson2ObjectMapperBuilder autoDetectGettersSetters(boolean autoDetectGettersSetters) {this.features.put(MapperFeature.AUTO_DETECT_GETTERS, autoDetectGettersSetters);this.features.put(MapperFeature.AUTO_DETECT_SETTERS, autoDetectGettersSetters);this.features.put(MapperFeature.AUTO_DETECT_IS_GETTERS, autoDetectGettersSetters);return this;}// MapperFeature#DEFAULT_VIEW_INCLUSIONpublic Jackson2ObjectMapperBuilder defaultViewInclusion(boolean defaultViewInclusion) {this.features.put(MapperFeature.DEFAULT_VIEW_INCLUSION, defaultViewInclusion);return this;}// DeserializationFeature#FAIL_ON_UNKNOWN_PROPERTIESpublic Jackson2ObjectMapperBuilder failOnUnknownProperties(boolean failOnUnknownProperties) {this.features.put(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, failOnUnknownProperties);return this;}// SerializationFeature#FAIL_ON_EMPTY_BEANSpublic Jackson2ObjectMapperBuilder failOnEmptyBeans(boolean failOnEmptyBeans) {this.features.put(SerializationFeature.FAIL_ON_EMPTY_BEANS, failOnEmptyBeans);return this;}// SerializationFeature#INDENT_OUTPUTpublic Jackson2ObjectMapperBuilder indentOutput(boolean indentOutput) {this.features.put(SerializationFeature.INDENT_OUTPUT, indentOutput);return this;}

3.6 混合注解

提供了直接添加混合注解类(覆盖某个类的注解)的相关方法:

	public Jackson2ObjectMapperBuilder mixIn(Class<?> target, Class<?> mixinSource) {this.mixIns.put(target, mixinSource);return this;}public Jackson2ObjectMapperBuilder mixIns(Map<Class<?>, Class<?>> mixIns) {this.mixIns.putAll(mixIns);return this;}

3.7 构建

用于构建一个ObjectMapper实例,每次调用都会返回一个新的对象,对于处理不同JSON格式或需要不同序列化/反序列化行为的场景,可以构建新的实例来处理。

	@SuppressWarnings("unchecked")public <T extends ObjectMapper> T build() {// 创建实例ObjectMapper mapper;if (this.createXmlMapper) {// 需要创建XmlMapper,则使用 XmlFactorymapper = (this.defaultUseWrapper != null ?new XmlObjectMapperInitializer().create(this.defaultUseWrapper, this.factory) :new XmlObjectMapperInitializer().create(this.factory));} else {// 不需要创建XmlMapper,则使用指定的工厂mapper = (this.factory != null ? new ObjectMapper(this.factory) : new ObjectMapper());}// 配置configure(mapper);return (T) mapper;}

3.8 配置

用于将成员属性都设置给已存在的ObjectMapper实例:

	public void configure(ObjectMapper objectMapper) {Assert.notNull(objectMapper, "ObjectMapper must not be null");// 注册模块MultiValueMap<Object, Module> modulesToRegister = new LinkedMultiValueMap<>();if (this.findModulesViaServiceLoader) {ObjectMapper.findModules(this.moduleClassLoader).forEach(module -> registerModule(module, modulesToRegister));} else if (this.findWellKnownModules : modulesToRegister.values()) {modules.addAll(nestedModules);}objectMapper.registerModules(modules);// 设置时间日期格式化if (this.dateFormat != null) {objectMapper.setDateFormat(this.dateFormat);}// 设置 Localeif (this.locale != null) {objectMapper.setLocale(this.locale);}// 设置 TimeZone	if (this.timeZone != null) {objectMapper.setTimeZone(this.timeZone);}// 设置 注解解析器if (this.annotationIntrospector != null) {objectMapper.setAnnotationIntrospector(this.annotationIntrospector);}// 设置属性名称策略if (this.propertyNamingStrategy != null) {objectMapper.setPropertyNamingStrategy(this.propertyNamingStrategy);}// 省略其他.........if (this.configurer != null) {this.configurer.accept(objectMapper);}}

3.9 其他

此外还提供了其他的方法,使用率较低,就不在一一讲解了。

	// 是否创建  XmlMapperpublic Jackson2ObjectMapperBuilder createXmlMapper(boolean createXmlMapper) {this.createXmlMapper = createXmlMapper;return this;}// 设置 JsonFactorypublic Jackson2ObjectMapperBuilder factory(JsonFactory factory) {this.factory = factory;return this;}// 设置 DateFormatpublic Jackson2ObjectMapperBuilder dateFormat(DateFormat dateFormat) {this.dateFormat = dateFormat;return this;}// 省略其他..........

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

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

相关文章

实现名校愿望|在站博士后赴英国剑桥大学做访问学者

国内博士后若再有国外名校背景加持&#xff0c;将会提升日后高校就职的准入门槛分量。为此&#xff0c;我们为Y博士申请到世界顶尖名校-英国剑桥大学的邀请函&#xff0c;在斩获学术成果的同时&#xff0c;也为出站后进入国内高校就职积累更丰富的背景。 Y博士背景&#xff1a;…

如何在CentOS本地部署FastDFS文件系统并实现无公网IP远程上传下载内网文件

文章目录 前言1. 本地搭建FastDFS文件系统1.1 环境安装1.2 安装libfastcommon1.3 安装FastDFS1.4 配置Tracker1.5 配置Storage1.6 测试上传下载1.7 与Nginx整合1.8 安装Nginx1.9 配置Nginx 2. 局域网测试访问FastDFS3. 安装cpolar内网穿透4. 配置公网访问地址5. 固定公网地址5.…

在一台恢复测试机器上验证oracle备份有效性

一 目的 定期将生产环境oracle数据库恢复到一台测试环境数据库服务器上&#xff0c;以验证备份是否有效&#xff0c;是否能正常恢复。 二 环境 这里以恢复orcl1库为例&#xff0c;计划在orcl这个实例上进行恢复测试。 三 实验步骤 3.1 在目标端创建和源端一样的备份目录 ①…

Pygame经典游戏:贪吃蛇

------------★Pygame系列教程★------------ Pygame经典游戏&#xff1a;贪吃蛇 Pygame教程01&#xff1a;初识pygame游戏模块 Pygame教程02&#xff1a;图片的加载缩放旋转显示操作 Pygame教程03&#xff1a;文本显示字体加载transform方法 Pygame教程04&#xff1a;dra…

「 网络安全常用术语解读 」软件成分分析SCA详解:从发展背景到技术原理再到业界常用检测工具推荐

软件成分分析&#xff08;Software Composition Analysis&#xff0c;SCA&#xff09;是一种用于识别和分析软件内部组件及其关系的技术&#xff0c;旨在帮助开发人员更好地了解和管理其软件的构建过程&#xff0c;同时可帮助安全人员揭秘软件内部结构的神秘面纱。SCA技术的发展…

大厂基础面试题(之四)

Q1&#xff1a;请先进行自我介绍 Q2&#xff1a;说下你学习前端的详细过程 Q3&#xff1a;一个页面从url输入到显示页面的整个过程 1.URL解析 2.DNS解析 3.建立TCP连接 4.发起HTTP请求 5.服务器处理请求 6.返回HTTP响应 7.下载页面资源 8.解析和渲染页面 9.JavaScript执行 10…

罗芬COHERENT pmb激光电源维修HPC830

Rofin激光电源 PMB高压电源维修:HPC625,HPC520,HPC210,HPC840,HPC830,HPC810,HPC818,HPC818 HPC814 HPC910等型号。 大型设备往往都配有功能较为故障诊断程序&#xff0c;我们可以充分利用软件的提示&#xff0c;缩小故障排查范围&#xff0c;但有时诊断软件提示的受损元件是否…

微信小程序实现全局参数共享,且实现全局参数变化时的页面间通信

首先&#xff0c;微信小程序中并没有提供直接的全局事件系统来监听全局参数的变化。因此&#xff0c;我们需要采用其他方式来达到这一目的。一种常见的方法是使用全局变量和事件监听来模拟全局事件系统。 1. 定义全局变量和事件 在 app.js 中定义全局变量&#xff0c;并提供一…

[ostream_iterator]输出Fibonacci数列

描述 Fibonacci数列指的是数列第一项和第二项为1&#xff0c;之后每一项是之前两项的和所构成的数列。 现有多组数据&#xff0c;每组数据给出一个数字n&#xff0c;请你输出Fibonacci数列的前n-1项。 #include <iostream> #include <iterator> using namespace …

UE5 GAS开发P32,33 初始化状态并绑定在HUD上,拾取物品增加血量和减少蓝量

这节课主要是修改WidgetController和OverlayController,在EffectActor内新增了一个减少蓝量的代码,同时修复了一个bug,并且展示了为什么要写成单独的控制器,因为要考虑多人游戏的情况,每一个控制器都是一个单独的角色 首先修改AuraAttirbuteSet.cpp UAuraAttributeSet::UAura…

【C++】unordered_map unordered_set 底层刨析

文章目录 1. 哈希表的改造2. unordered_map3. unordered_set C STL 库中&#xff0c;unordered_map 和 unordered_set 容器的底层为哈希表&#xff0c;本文将简单模拟哈希表&#xff08;哈希桶&#xff09;&#xff0c;unordered_map 和 unordered_set 只需封装哈希表的接口即可…

C语言中static变量和普通变量有什么区别?

下面将从变量的存储周期和可见性&#xff0c;以及函数的链接属性等方面展开 1. static全局变量和普通全局变量有什么区别? static全局变量和普通全局变量都存储在静态存储区, 生命周期都是整个文件运行结束 但是, 普通全局变量在所有源文件中都是可见的, 如果一个源文件中定…

kylin Firefox Warning: Potential Security Risk Ahead

Warning: Potential Security Risk Ahead &#xfeff; Firefox detected a potential security threat and did not continue to 127.0.0.1. If you visit this site, attackers could try to steal information like your passwords, emails, or credit card details. 警告&…

java实现简单图书管理系统(附带源码)

项目要求 该项目会用到类和对象&#xff0c;封装、继承、多态、接口、等&#xff0c;会帮你巩固并加强这类知识 设计要求及思路 1.要求有两套系统分别给管理员和普通用户使用&#xff0c;经过开始的选择会有两个对应功能不同的菜单&#xff0c;这里两种角色我们可以放一个包…

华为ensp中nat地址转换(静态nat 动态nat NAPT 和Easy IP)配置命令

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年4月15日12点03分 实验拓扑 接下来我会分几个方面初步将静态nat和napt easy ip 首先基本的环境配置 AR1的基本配置 //基本的IP配置和默认路由指向外网 <Huawei&…

神仙级Python入门教程(超级详细),从零基础入门到精通,从看这篇开始

一、初聊Python 1.为什么要学习Python&#xff1f; 在学习Python之前&#xff0c;你不要担心自己没基础或“脑子笨”&#xff0c;我始终认为&#xff0c;只要你想学并为之努力&#xff0c;就能学好&#xff0c;就能用Python去做很多事情。在这个喧嚣的时代&#xff0c;很多技…

linux 数据链路层 socket编程 广播

在Linux系统中&#xff0c;要进行数据链路层的socket编程&#xff0c;并发送广播包&#xff0c;你可以使用原始套接字&#xff08;raw socket&#xff09;&#xff0c;并将IP头设置为广播地址。以下是一个简单的例子&#xff0c;展示如何使用原始套接字在数据链路层发送广播包&…

分布式锁介绍

引言 分布式锁是一种用于协调不同进程或线程对共享资源的访问控制的机制。在分布式系统中&#xff0c;由于多个节点可能同时访问或修改同一资源&#xff0c;因此需要一个中心化的协调机制来确保资源的访问是有序的&#xff0c;避免数据不一致的问题。 分布式锁的特性&#xf…

电子元器件供应链的优化与改进

优化和改进电子元器件供应链是确保企业竞争力和业务成功的关键一步。以下是一些优化和改进电子元器件供应链的方法&#xff1a;      供应链网络设计&#xff1a; 重新评估和优化供应链网络&#xff0c;确定最佳的供应商和分销商位置&#xff0c;以最大程度地降低成本、提高…

Java反序列化-(LazyMap)CC1链与CC6链

(LazyMap)CC1链 原版的CC1链&#xff1a; https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java可以发现对比之前的 TransformMap版本的CC1链&#xff0c;从这里开始就不一样了 分析LazyMap.get() 直接进入到Laz…