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初始化的过程。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot 整合RocketMQ

目录 一、引入依赖 二、配置文件 三、生产者 四、消费者 五、结果 一、引入依赖 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.2.0</version> </d…

Flutter - flutter_gen 资源管理

引言&#xff1a; 在开发 Flutter 应用时&#xff0c;我们经常需要使用各种静态资源&#xff0c;如图片、字体和音频等。如何有效地管理和加载这些资源呢&#xff1f;本篇博客将以图片为例带你解密 Flutter 项目中是如何管理资源地。 assets 加载资源 具体文件名引入 在工程…

【1500字干货】6大实用技巧,轻松在1688找到优质货源厂家!

1688平台提供了海量的选品机会&#xff0c;并且汇聚了大量的优质源头厂家。对于想要寻找高质量、有竞争力的产品的商家来说&#xff0c;1688平台是一个非常好的选择。然而&#xff0c;在选择源头厂家时&#xff0c;商家也需要注意一些问题。好的货源很重要&#xff0c;可是如何…

Linux/Lame

Lame 今天随便乱逛发现这台机器貌似是 HackTheBox 平台的第一台机器&#xff0c;而且我还没做过&#xff0c;从简介上来看的话是一台很简单的机器&#xff0c;快快的玩一下 Enumeration nmap 首先用 nmap 扫描一下常见的端口&#xff0c;发现系统对外开放了 21,22,139,445 端…

《剑指 Offer》专项突破版 - 面试题 105 和 106 : 最大的岛屿和二分图(C++ 实现)

目录 面试题 105 : 最大的岛屿 面试题 106 : 二分图 面试题 105 : 最大的岛屿 题目&#xff1a; 海洋岛屿地图可以用由 0、1 组成的二维数组表示&#xff0c;水平或竖直方向相连的一组 1 表示一个岛屿&#xff0c;请计算最大的岛屿的面积&#xff08;即岛屿中 1 的数目&…

如何使用Jellyfin+cpolar低成本部署私人影音平台并实现无公网IP远程访问

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及&#xff0c;各种各样的使用需求也被开发出来&…

事务的隔离性

参考: 小林coding MySQL服务器同时处理多个事务时&#xff0c;会出现脏读&#xff0c;不可重复读&#xff0c;幻读问题。 脏读 一个事务读到另一个未提交事务修改过的数据。 举例&#xff1a;事务A先读取数据&#xff0c;并对其进行修改&#xff0c;此时事务B进行读取获取到…

【python】实时获取当前屏幕图像

一、代码 import pyautogui import cv2 import numpy as np import time # 获取屏幕尺寸 screen_width, screen_height pyautogui.size() screen_size (1920, 1080) cv2.namedWindow("Screen Capture", cv2.WINDOW_NORMAL) # cv2.resizeWindow("Screen Captu…

大话设计模式——21.中介者模式(Mediator Pattern)

简介 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互 UML图 应用场景 大量的连接使得一个对象不可能在没有其他对象的支持下工作&#xff0c;系统表现为一个不可分割的…

视频压缩软件有哪些?教你免费压缩视频的方法。

视频文件通常占据较大的存储空间&#xff0c;压缩视频可以有效节省存储成本&#xff0c;并使得视频文件更容易在网络上分享和传输。在网络带宽有限的情况下&#xff0c;压缩视频可以减少视频流量&#xff0c;提高视频在低带宽环境下的流畅性和观看体验。哪款视频压缩软件最好用…

海外云手机提供的当地IP有什么好处?

在全球化的数字时代&#xff0c;海外云手机成为许多企业和个人的首选&#xff0c;用于运营海外社媒、远程办公等活动。海外云手机的一个重要特点是可以选择不同国家的IP地址&#xff0c;以实现更灵活的运营策略和网络访问控制。 首先&#xff0c;让我们探讨海外云手机可以选不同…

element vue 日期时间组件封装

一、背景 年、月、周、日的时间范围类型&#xff0c;选择对应的日期类型&#xff0c;会传参给后端一个dateType参数&#xff0c;用于后端判断&#xff0c;进行数据抽稀。 二、实现效果 三、代码 完整代码&#xff1a; //年月周日&#xff0c;组件封装 //vue3 setup <scrip…

10. 学生成绩管理系统

内容概要 认识了解数组 可重复添加数组的命令 认识并了解数组 1.什么是数组 数组用来存储一组同类型的数据 2.数组的使用 创建数组 使用数组&#xff1a;加入成员、获取数组中成员的内容&#xff08;值&#xff09;、删除成员、取数组成员数、清除数组 3.需要注意的问…

通信指挥类装备(多链路聚合设备)

随着信息技术的迅猛发展&#xff0c;通信指挥类装备在应急管理等领域中发挥着越来越重要的作用。多链路聚合设备具有4G/5G、专网、卫星网、宽带自组网、WiFi等多种网络接入和融合能力&#xff0c;同时使用用户≥200&#xff0c;防护等级≥IP66&#xff0c;单电池可连续工作≥4h…

Prometheus接入AlterManager配置邮件告警(基于K8S环境部署)

目录 一.配置Alertmanager告警发送至邮箱二.Prometheus接入AlertManager三.部署PrometheusAlterManager(放到一个Pod中)四. 测试告警 基于 此环境做实验 一.配置Alertmanager告警发送至邮箱 1.创建AlertManager ConfigMap资源清单 vim alertmanager-cm.yaml --- kind: Confi…

C++ 中的默认成员函数详解

在 C 中&#xff0c;有六种默认成员函数会在创建类时由编译器自动生成。但需要注意的是&#xff0c;如果我们手动在类中定义了其中一种成员函数&#xff0c;编译器便不会自动生成该成员函数。 构造函数 作用&#xff1a;构造函数在实例化对象时自动被调用&#xff0c;用于初始化…

Ubuntu 安装Java、Git、maven、Jenkins等持续集成环境

Ubuntu 持续集成 安装OpenJdk 查看所有可安装的 JDK 版本 apt list OpenJDK\*使用 apt 安装 JDK&#xff08;以 11为例&#xff09;,最好是用11&#xff0c;java8对应的jenkins会有兼容问题。 sudo apt install openjdk-11-jdk openjdk-11-jre安装成功后&#xff0c;可以使用以…

IP地址定位技术在各领域的作用

IP地址定位是通过确定IP地址的物理位置来定位一个设备的技术&#xff0c;它在现代社会的多个领域中都有着广泛的应用。以下将详细探讨IP地址定位的应用场景&#xff0c;以期对读者有所启发。 首先&#xff0c;在网络安全领域&#xff0c;IP地址定位发挥着至关重要的作用。网络…

6、Qt-button设置

前言&#xff1a;记录Button使用的一些技巧 一、无边框前端设置 二、无边框后台设置 ui->PushButton->setStyleSheet("border:none;") 四、参考文献 4.1 Qt按钮实现无边框效果的方法之一_qt设置按钮无边框-CSDN博客

Linux 秋招必知必会(一、文件I/O、文件和目录)

一、基本概念 1. shell shell&#xff1a;命令解释器&#xff0c;根据输入的命令执行相应命令 bash&#xff08;Bourne-Again-SHell&#xff09;是一个为 GNU 计划编写的 Unix shellLinux 默认的 shell&#xff1a;/bin/bash 2. 类 Unix 系统目录结构 Ubuntu 没有盘符这个…