springboot中json转换LocalDateTime失败的bug解决过程

摘要:
环境:jdk1.8、maven、springboot问题:前端通过json传了一个日期:date:2019-03-01(我限制不了前端开发给到后端的日期为固定格式,有些人就是这么不配合), 而springboot中默认使用jackson做json序列化和反序列化,后台接收数据时将日期字符串转成LocalDateTime时,会报错:1Causedby:com.fasterxml.jackson.da

环境:jdk1.8、maven、springboot

问题:前端通过json传了一个日期:date:2019-03-01(我限制不了前端开发给到后端的日期为固定格式,有些人就是这么不配合), 

而springboot中默认使用jackson做json序列化和反序列化,后台接收数据时将日期字符串转成LocalDateTime时,会报错:

1 Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDateTime` from String "2019-03-01":Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2019-03-01' could not be parsed at index 10
2 
3   at [Source: (PushbackInputStream); line: 1, column: 10] (through reference chain: com.XXX.vo.XXXExtVo["date"])
4   at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
5   at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1549)
6   at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:911)
7   at com.fasterxml.jackson.datatype.jsr310.deser.JSR310DeserializerBase._handleDateTimeException(JSR310DeserializerBase.java:80)
8   at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer.deserialize(LocalDateTimeDeserializer.java:84)
9   at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer.deserialize(LocalDateTimeDeserializer.java:39)

解决过程:

1.通过百度,参考了大神的解决方法:https://blog.csdn.net/a13794479495/article/details/83892829

2.maven引入依赖

1         <dependency>
2             <groupId>com.fasterxml.jackson.datatype</groupId>
3             <artifactId>jackson-datatype-jsr310</artifactId>
4             <version>2.9.7</version>
5         </dependency>    

3.增加配置类:LocalDateTimeSerializerConfig

1 @Configuration
2 public classLocalDateTimeSerializerConfig {
3 @Bean
4   publicObjectMapper serializingObjectMapper() {
5     JavaTimeModule module = newJavaTimeModule();
6     LocalDateTimeDeserializer dateTimeDeserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
7     module.addDeserializer(LocalDateTime.class, dateTimeDeserializer);
8     returnJackson2ObjectMapperBuilder.json().modules(module)
9 .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).build();
10 }
11 }

4.由于自定义的LocalDateTimeDeserializer反序列化器只能设置一种格式:yyyy-MM-dd HH:mm:ss,所以我遇到的问题还是没有解决

5.对程序进行debug,发现反序列化操作是由LocalDateTimeDeserializer中的deserialize()方法进行反序列化操作的:

1 public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throwsIOException {
2     if (parser.hasTokenId(6)) {//核心代码
3       String string =parser.getText().trim();
4       if (string.length() == 0) {
5         return null;
6       } else{
7         try{
8           if (this._formatter == DEFAULT_FORMATTER && string.length() > 10 && string.charAt(10) == 'T') {
9             return string.endsWith("Z") ?LocalDateTime.ofInstant(Instant.parse(string), ZoneOffset.UTC) : LocalDateTime.parse(string, DEFAULT_FORMATTER);
10           } else{
11             return LocalDateTime.parse(string, this._formatter);
12 }
13         } catch(DateTimeException var12) {
14           return (LocalDateTime)this._handleDateTimeException(context, var12, string);
15 }
16 }
17     } else{
18       if(parser.isExpectedStartArrayToken()) {
19         JsonToken t =parser.nextToken();
20         if (t ==JsonToken.END_ARRAY) {
21           return null;
22 }
23 
24 .........
25 .........
26 .........
27 
28         return (LocalDateTime)this._handleUnexpectedToken(context, parser, "Expected array or string.", new Object[0]);
29 }
30 }
31   }

6.自定义一个MyLocalDateTimeDeserializer反序列化器(复制原来LocalDateTimeDeserializer类中的所有代码,粘贴到自定义的MyLocalDateTimeDeserializer中,修改构造器名及静态域中的相关代码)

7.然后修改MyLocalDateTimeDeserializer中的deserialize()方法

1 //这里只是简单的根据前端传过来的日期字符串进行简单的处理,然后再进行类型转换
2 //这段代码中有很多漏洞,只是针对常用格式做了简单处理,请慎用!或自己做更全面的考虑并相应的修改!(只是提供了这样一种解决思路)
3 public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throwsIOException {
4     if (parser.hasTokenId(6)) {
5         String string = parser.getText().trim().replace("/", "-");//yyyy/MM/dd替换为yyyy-MM-dd
6         if (string.length() == 0) {
7           return null;
8 }
9         try{
10           if (this._formatter == DEFAULT_FORMATTER && string.length() > 10 && string.charAt(10) == 'T') {
11             return string.endsWith("Z") ?LocalDateTime.ofInstant(Instant.parse(string), ZoneOffset.UTC) : LocalDateTime.parse(string, DEFAULT_FORMATTER);
12           } else if (string.length() > 10 && string.charAt(10) == 'T') { //处理yyyy-MM-ddTHH:mm:ss.sssZ的格式
13             return string.endsWith("Z") ?LocalDateTime.ofInstant(Instant.parse(string), ZoneOffset.UTC) : LocalDateTime.parse(string, DEFAULT_FORMATTER);
14           } else if (string.length() == 10) {//处理yyyy-MM-dd的格式
15             return LocalDateTime.parse(string + " 00:00:00", this._formatter);
16           } else {//配置第三步的时候,设置了时间格式为:yyyy-MM-dd HH:mm:ss
17             return LocalDateTime.parse(string, this._formatter);
18 }
19         } catch(DateTimeException var12) {
20           return this._handleDateTimeException(context, var12, string);
21 }
22     } else{
23       if(parser.isExpectedStartArrayToken()) {
24 ..........
25 ..........
26 ..........
27         ..........

8.在之前第三步的 LocalDateTimeSerializerConfig配置文件中,修改第六行的代码为:

MyLocalDateTimeDeserializer dateTimeDeserializer = new MyLocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

9.重启服务,验证是否问题解决。

此文仅为记录个人实践中遇到的问题及解决思路。如有雷同,仅可参考!

免责声明:文章转载自《springboot中json转换LocalDateTime失败的bug解决过程》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇MySQL配置主主及主从备份CentOS7 配置阿里云yum源,非常之简单下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【216】◀▶ IDL 字符串操作说明 (黑底)

参考:String Processing Routines —— 字符串处理函数 参考:IDL_String Methods 01   STRING 返回字符串。 02   STRCMP 比较字符串,一样返回1,不一样返回0,默认大小写敏感。 03   STRMATCH 字符串进行比较,一致返回1,不一致返回0。 04   STRCOMP...

精通shell编程--最后的总结

不得不说shell语法是丑陋的,操作是简单高效的,最后一次学习总结shell shell总结 字符串删除与替换等常见操作 ## 字符串长度 a=1234 echo "${#a}" expr length "${a}" ## 字符串 索引 expr index ${a} 23 # 拆分 2 3 一个个查找找到第一个匹配的就返回 ## 字符串 匹配 有问...

消息队列之 ActiveMQ

简介 ActiveMQ 特点 ActiveMQ 是由 Apache 出品的一款开源消息中间件,旨在为应用程序提供高效、可扩展、稳定、安全的企业级消息通信。 它的设计目标是提供标准的、面向消息的、多语言的应用集成消息通信中间件。ActiveMQ 实现了 JMS 1.1 并提供了很多附加的特性,比如 JMX 管理、主从管理、消息组通信、消息优先级、延迟接收...

c# 实现网页上用户自动登陆|asp.net 模拟网站登录

using System;using System.Collections.Generic;using System.Text;using System.Net;using System.IO; namespace Czt.Web{ /// <summary> /// 实现网站登录类 /// </summary> public cl...

对json进行封装

项目中经常用到对于JSON的各种转换处理,保存一份,免得以后忘了。 using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.Data; using System.Collections; using CR...

Java大文件分片上传/多线程上传

这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得出来,实体类中已经有很多我们需要的功能了,还有实用的属性。如MD5秒传的信息。 public class FileInf {      public File...