Jackson配置处理LocalDateTime、LocalDate等java8时间类型失效的问题解决

目录

前言

一、问题排查过程

1.1 SpringMvc是如何处理请求报文和响应报文

1.2 JacksonConfig配置排查

二、导致Jackson配置失效的原因

2.1 没有addSerializer

2.2 添加了@EnableMvc注解

2.3 另外有地方配置了Jacksonhttpconver覆盖了配置

总结


前言

上一篇文章《使用Jackson进行序列化和反序列化》中指出,Jackson默认是不支持处理java8的时间类型如:LocalDateTime类型会被序列化成带T的时间格式。需要在字段上面添加@DateFomter或者在ObjectMapper中注册JavaTimeModule。但是注册JavaTimeModule的方式我这边一直没有效果,时间类型并没有安装我设置的去格式化。本篇文章是我排查我的配置为何不生效,并最终找到原因使配置生效的过程。


首先我把我的配置先贴出来,有经验的大神应该一眼就看出来导致我时间格式化模块配置没生效的原因了,但是我在排查的时候累计花费时间有一天了。

@Configuration
public class JacksonConfig {@Bean("objectMapper")@Primary@ConditionalOnMissingBean(ObjectMapper.class)public ObjectMapper getObjectMapper(Jackson2ObjectMapperBuilder builder) {ObjectMapper mapper = builder.build();// 日期格式mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));//GMT+8//map.put("CTT", "Asia/Shanghai");mapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));JavaTimeModule javaTimeModule = new JavaTimeModule();javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));javaTimeModule.addSerializer(new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));javaTimeModule.addSerializer(new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN)));javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));mapper.registerModule(javaTimeModule);//Include.NON_NULL 属性为NULL 不序列化//ALWAYS // 默认策略,任何情况都执行序列化//NON_EMPTY // null、集合数组等没有内容、空字符串等,都不会被序列化//NON_DEFAULT // 如果字段是默认值,就不会被序列化//NON_ABSENT // null的不会序列化,但如果类型是AtomicReference,依然会被序列化mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);//允许字段名没有引号(可以进一步减小json体积):mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);//允许单引号:mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);// 允许出现特殊字符和转义符//mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);这个已经过时。mapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);//允许C和C++样式注释:mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);//序列化结果格式化,美化输出mapper.enable(SerializationFeature.INDENT_OUTPUT);//枚举输出成字符串//WRITE_ENUMS_USING_INDEX:输出索引mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);//空对象不要抛出异常:mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);//Date、Calendar等序列化为时间格式的字符串(如果不执行以下设置,就会序列化成时间戳格式):mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);//反序列化时,遇到未知属性不要抛出异常:mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);//反序列化时,遇到忽略属性不要抛出异常:mapper.disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES);//反序列化时,空字符串对于的实例属性为null:mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);return mapper;}
}

我在网上找了很多方法,但是都没有解决我的问题,所以没办法只能想着静下心来,通过查看源码的方式来排查问题了 

一、问题排查过程

1.1 SpringMvc是如何处理请求报文和响应报文

这个我之前的文章有写过,这里就直接引用之前的文章了《深入探究Spring MVC如何处理请求报文和响应报文》根据文章中的内容,处理响应报文的地方是在RequestResponseBodyMethodProcessor#handleReturnValue中。这这里的逻辑的意思就是根据请求头和响应头里面的类型type找到处理响应报文的HttpMessageConverter。

这里直接看结果,最终用来序列化的HttpMessageConvertObjectMapper中的LocalDateTimeSerializer中根本就没有formatter,说明在config中配置的JavaTimeModel并没有生效。但是其他的配置却生效了。

通过上面的分析,可以推断出肯定是MappingJackson2HttpMessageConverter在生成的时候并没有将我在ObjectMapperConfig中配置的JavaTimeModel给带进去。

1.2 JacksonConfig配置排查

  通过上面的排查,知道JavaTimeModel配置未生效,但是其它的配置却是没问题的,所以JacksonConfig中的其它配置是没问题的。下面要排查只能看MappingJackson2HttpMessageConverter生成的地方了这时候我想起了上次也试了一个配置的方法是有效的,就是在Jackson2ObjectMapperBuilder上直接注册model。直接注册model有效,在ObjectMapper上注册就没效果。难道是Jackson2ObjectMapperBuilder没有读取ObjectMapper中的配置,或者是注册之前已经读取了。

想到这里我就想点开这一段代码看一下

ObjectMapper mapper = builder.build();

因为我怀疑build方法是重新创建了一个对象返回了(其实这个想法有点荒谬,重新创建一个就有两个ObjectMapper了,那就是一个ObjectMapper配置一半了)。 所以我就进入代码一探究竟。

大概的意思是Model已经注册好了,所以是build方法不能调用。所以后面我就将配置改成

ObjectMapper mapper = new ObjectMapper();

果然就配置生效了。 

二、导致Jackson配置失效的原因

2.1 没有addSerializer

如果配置Jackson的时候,只是添加了JavaTimeModel,是不会生效的。需要添加LocalDateTimeSerializerLocalDateTimeDeserializerLocalTimeSerializerLocalDateDeserializerLocalDateSerializerLocalTimeDeserializer才会够成功序列化和反序列化时间类型。

2.2 添加了@EnableMvc注解

直接参考这个《jackson全局配置没有生效》

2.3 另外有地方配置了Jacksonhttpconver覆盖了配置

需要自己找到其它配置的地方,或者在配置上添加@Primary注解


总结

本文主要是上个章节留下来的问题,关于builder.build()导致model已经被加载过了的问题似乎我没有说清楚,主要是也不想花时间深究了,有空再去看看MappingJackson2HttpMessageConverter初始化的过程。

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

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

相关文章

【matlab】如何解决打开缓慢问题(如何让matlab在十几秒内打开)

【matlab】如何解决打开缓慢问题(如何让matlab在十几秒内打开) 找到我们解压缩时Crack中的license_standalone.lic文件,将其拷贝 在安装matlab的路径下新建一个文件,粘贴上面的license_standalone.lic文件 在桌面鼠标移动到matl…

【Linux系列】如何确定当前运行的是 RHEL 9 还是 RHEL 8?

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

lua学习笔记13(一些特殊用法的学习和三目运算符的实现)

print("*****************************一些特殊用法的学习*******************************") print("*****************************多变量赋值*******************************") local a,b,c114514,8848,"凌少" print(a) print(b) print(c) -…

DAS-MIL

DAS-MIL论文笔记 题目:DAS-MIL: Distilling Across Scales for MIL Classification of Histological WSIs 摘要 近年来,采用多实例学习 (MIL) 对全玻片图像 (WSI) 进行分类的情况有所增加。事实上&#…

VUE3的有关知识

学习vue3的原因 在vue2当中的组件的实例,都是data一块,computed一块,当我们去找某一变量相关的则十分麻烦,vue3是组合式API,vue2是选项式, vue3的优点: 1)组合式更易维护 2)更快的速度 3)更小的体积 4)更好的响应式proxy 使用vue3相关脚手架创建项目 步骤: 1)node -v node版…

pycharm pyspark连接虚拟机的hive表 读取数据

方法&#xff1a; hive配置hiveserver2和metastore url <!-- 指定hiveserver2连接的host --> <property><name>hive.server2.thrift.bind.host</name><value>hadoop111</value> </property><!-- 指定hiveserver2连接的端口号 -…

大数据基本名词

目录[-] 1.1. 1. Hadoop1.2. 2. Hive1.3. 3. Impala1.4. 4. Hbase1.5. 5.hadoop hive impala hbase关系1.6. 6. Spark1.7. 7. Flink1.8. 8. Spark 和 Flink 的应用场景 1. Hadoop 开源官网&#xff1a;https://hadoop.apache.org/ Hadoop是一个由Apache基金会所开发的分…

进程创建fork进程终止

文章目录 进程创建fork函数fork函数返回值写时拷贝子进程功能fork调度失败的原因 进程终止进程终止的概念进程终止的情况退出码&&退出信号 进程退出方法exit与_exit的区别 进程创建 进程&#xff1a;内核数据结构&#xff08;task_struct &#xff0c;mm_struct &…

基于Spring Boot+Vue的在线拍卖系统

随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单管理、…

页面转word的那些事

背景 有些时候需要将页面内容或者是页面的数据通过word进行下载&#xff0c;以方便客户进行二次编辑&#xff0c;而不是直接导出图片或者是pdf。 想在页面端点击下载成word&#xff0c;那必然需要服务端来进行读写文件&#xff0c;无论是你后端编辑好的内容流&#xff0c;还是…

第十四篇【传奇开心果系列】Python自动化办公库技术点案例示例:深度解读Python自动化处理图像

传奇开心果博文系列 系列博文目录Python自动化办公库技术点案例示例系列 博文目录前言一、Python自动化图像处理的优点介绍二、Python常用图像处理库和功能介绍三、强大且易于上手示例代码四、丰富的算法资源示例代码五、批量处理图片示例代码六、支持多种图像格式示例代码七、…

智慧粮仓监测系统解决方案

一、概述 粮食储备是每个国家战略物资中最为重要的一项储备&#xff1b;而随着现代化农业的快速发展以及国家经济发展的需要&#xff0c;我国粮食产量和储备量长期处于世界前列。传统的粮仓由于修建年代久远&#xff0c;可能存在着设施落后&#xff0c;实时监控不到位的现象&am…

python-study-day1

ps&#xff1a;前言 可做毕设&#xff0c;html&#xff0c;web&#xff0c;app&#xff0c;小程序&#xff0c;bug修改&#xff0c;可加急 作者自述 作为一名前端开发工程师&#xff0c;这个大环境不好的情况下&#xff0c;我试过我前端接单子但是没有后端&#xff0c…

物理随机接入信道PRACH数据生成

NR随机接入前导码&#xff08;Preamble&#xff09;采用Zadoff Chu序列&#xff0c;长度分别为839和139。 物理随机接入信道&#xff08;PRACH&#xff09;前导码格式的定义包括PRACH OFDM符号个数、循环前缀&#xff08;CP&#xff09;长度和保护时间&#xff08;GT&#xff…

0 idea搭建springboot项目

1 2 3 4 5 配置文件 application.yaml server:servlet:context-path: /app #项目名controller //注入到spring容器 Controller public class HelloController {GetMapping("hello")ResponseBodypublic String hello(){return "Hello,SpringBoot";} }启…

WinRAR再爆0 day漏洞,0 day漏洞该如何有效预防

WinRAR再爆0 day漏洞&#xff0c;已被利用超过4个月。 Winrar是一款免费的主流压缩文件解压软件&#xff0c;支持绝大部分压缩文件格式的解压&#xff0c;全球用户量超过5亿。Group-IB研究人员在分析DarkMe恶意软件时发现WinRAR在处理ZIP文件格式时的一个漏洞&#xff0c;漏洞…

虚拟网络设备的真正使命:实现有控制的通信

在数字化时代&#x1f4f2;&#xff0c;网络安全&#x1f512;成为了企业和个人防御体系中不可或缺的一部分。随着网络攻击的日益复杂和频繁&#x1f525;&#xff0c;传统的物理网络安全措施已经无法满足快速发展的需求。虚拟网络设备&#x1f5a7;&#xff0c;作为网络架构中…

从挑战到机遇:HubSpot如何帮助企业化解出海过程中的难题

企业出海挑战与对策 随着全球化的加速推进&#xff0c;越来越多的企业开始将目光投向海外市场&#xff0c;以寻求更广阔的发展空间。然而&#xff0c;在出海的过程中&#xff0c;企业往往面临着诸多挑战&#xff0c;其中文化差异、法律限制等问题尤为突出。今天运营坛将对这些…

LeetCode 题目:两个总和

LeetCode 题目&#xff1a;两个总和 描述&#xff1a; 编写一个函数&#xff0c;输入为一个整数数组nums和一个目标整数target&#xff0c;要求找到数组中两个数的和等于target&#xff0c;并返回这两个数的索引。 函数定义&#xff1a; def two_sum(nums: List[int], targe…