zoukankan      html  css  js  c++  java
  • springboot中json转换LocalDateTime失败的bug解决过程

    环境: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 class LocalDateTimeSerializerConfig {
     3   @Bean
     4   public 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);
     8     return 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()方法进行反序列化操作的:

     1 public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {
     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) throws IOException {
     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.重启服务,验证是否问题解决。

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

  • 相关阅读:
    array_udiff_assoc — 带索引检查计算数组的差集,用回调函数比较数据
    array_sum — 对数组中所有值求和
    array_splice — 去掉数组中的某一部分并用其它值取代
    array_slice — 从数组中取出一段
    array_multisort — 对多个数组或多维数组进行排序
    array_merge — 合并一个或多个数组
    array_keys — 返回数组中部分的或所有的键名
    array_key_exists — 检查数组里是否有指定的键名或索引
    array_intersect_assoc — 带索引检查计算数组的交集
    array_flip — 交换数组中的键和值
  • 原文地址:https://www.cnblogs.com/beilife/p/10626233.html
Copyright © 2011-2022 走看看