springboot中json转换LocalDateTime失败的bug解决过程
环境:jdk1.8、maven、springboot
问题:前端通过json传了⼀个⽇期:date:2019-03-01(我限制不了前端开发给到后端的⽇期为固定格式,有些⼈就是这么不配合), 
  ⽽springboot中默认使⽤jackson做json序列化和反序列化,后台接收数据时将⽇期字符串转成LocalDateTime时,会报错:
1 Caused by: com.fasterxml.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDateTime` from String "2019-03-01":Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseExc 2
3  at [Source: (PushbackInputStream); line: 1, column: 10] (through reference chain: com.XXX.vo.XXXExtVo["date"])
4  at com.fasterxml.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)
解决过程:
  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
2public class LocalDateTimeSerializerConfig {
3  @Bean
4public ObjectMapper serializingObjectMapper() {
5    JavaTimeModule module = new JavaTimeModule();
6    LocalDateTimeDeserializer dateTimeDeserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
7    module.addDeserializer(LocalDateTime.class, dateTimeDeserializer);
8return Jackson2ObjectMapperBuilder.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()⽅法进⾏反序列化操作的:
1public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {
2if (parser.hasTokenId(6)) {//核⼼代码
3      String string = Text().trim();
4if (string.length() == 0) {
5return null;
6      } else {
7try {
8if (this._formatter == DEFAULT_FORMATTER && string.length() > 10 && string.charAt(10) == 'T') {
dsWith("Z") ? LocalDateTime.ofInstant(Instant.parse(string), ZoneOffset.UTC) : LocalDateTime.parse(string, DEFAULT_FORMATTER);
10          } else {
11return LocalDateTime.parse(string, this._formatter);
12          }
13        } catch (DateTimeException var12) {
14return (LocalDateTime)this._handleDateTimeException(context, var12, string);
15        }
16      }
17    } else {
18if (parser.isExpectedStartArrayToken()) {
19        JsonToken t = Token();
20if (t == JsonToken.END_ARRAY) {
21return null;
22        }
23
24 .........
25 .........
26 .........
27
28return (LocalDateTime)this._handleUnexpectedToken(context, parser, "Expected array or string.", new Object[0]);
29      }
30    }
31  }
  6.⾃定义⼀个MyLocalDateTimeDeserializer反序列化器(复制原来LocalDateTimeDeserializer类中的所有代码,粘贴到⾃定义的MyLocalDateTimeDeserializer中,修改构
造器名及静态域中的相关代码)
  7.然后修改MyLocalDateTimeDeserializer中的deserialize()⽅法
1//这⾥只是简单的根据前端传过来的⽇期字符串进⾏简单的处理,然后再进⾏类型转换
2//这段代码中有很多漏洞,只是针对常⽤格式做了简单处理,请慎⽤!或⾃⼰做更全⾯的考虑并相应的
修改!(只是提供了这样⼀种解决思路)
3public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {
4if (parser.hasTokenId(6)) {
5        String string = Text().trim().replace("/", "-");//yyyy/MM/dd替换为yyyy-MM-dd
6if (string.length() == 0) {
7return null;
8        }
9try {
10if (this._formatter == DEFAULT_FORMATTER && string.length() > 10 && string.charAt(10) == 'T') {
dsWith("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的格式
dsWith("Z") ? LocalDateTime.ofInstant(Instant.parse(string), ZoneOffset.UTC) : LocalDateTime.parse(string, DEFAULT_FORMATTER);
14          } else if (string.length() == 10) {//处理yyyy-MM-dd的格式
invalids15return LocalDateTime.parse(string + " 00:00:00", this._formatter);
16          } else {//配置第三步的时候,设置了时间格式为:yyyy-MM-dd HH:mm:ss
17return LocalDateTime.parse(string, this._formatter);
18          }
19        } catch (DateTimeException var12) {
20return this._handleDateTimeException(context, var12, string);
21        }
22    } else {
23if (parser.isExpectedStartArrayToken()) {
24        ..........
25        ..........
26        ..........
27        ..........
  8.在之前第三步的 LocalDateTimeSerializerConfig 配置⽂件中,修改第六⾏的代码为:
MyLocalDateTimeDeserializer dateTimeDeserializer = new MyLocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
  9.重启服务,验证是否问题解决。
此⽂仅为记录个⼈实践中遇到的问题及解决思路。如有雷同,仅可参考!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。