解决jackson反序列化失败InvalidFormatException:Can not deserialize value of type java.util.Date

 更新时间:2023年12月26日 17:07:08   作者:huangyaa729  
这篇文章主要介绍了解决jackson反序列化失败InvalidFormatException:Can not deserialize value of type java.util.Date问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

今天调试接口的时候碰到了这个问题,String 转Date类型时

反序列化失败

caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException:
Can not deserialize value of type java.util.Date from String
“2018-12-25 10:07:49”: not a valid representation (error: Failed to
parse Date value ‘2018-12-25 10:07:49’: Can not parse date “2018-12-25
10:07:49Z”: while it seems to fit format
‘yyyy-MM-dd’T’HH:mm:ss.SSS’Z’’, parsing fails (leniency? null))

首先尝试了 @DateTimeFormat注解,发现没有效果,仍然报错;

然后试了下@JsonFormat注解,接口正常;

在印象中,@DateTimeFormat是入参时进行数据格式化转换,@JsonFormat是出参进行格式话转换,为啥突然不行了呢。

通过一番搜索,找到了如下解释

一般都是使用@DateTimeFormat把传给后台的时间字符串转成Date,使用@JsonFormat把后台传出的Date转成时间字符串,但是@DateTimeFormat只会在类似@RequestParam的请求参数(url拼接的参数才生效,如果是放到RequestBody中的form-data也是无效的)上生效,如果@DateTimeFormat放到@RequestBody下是无效的。

在@RequestBody中则可以使用@JsonFormat把传给后台的时间字符串转成Date,也就是说@JsonFormat其实既可以把传给后台的时间字符串转成Date也可以把后台传出的Date转成时间字符串。

至于为啥没效果,没有细说,从报错的分析来看应该是反序列话的方式不同,导致@DateTimeFormat注解不能生效。

另附原因与多种解决方式

原因

fastjson默认使用的序列化格式:

public static String DEFFAULT_DATE_FORMAT = “yyyy-MM-dd
HH:mm:ss”;

jackson默认支持的日期反序列格式:

(“yyyy-MM-dd'T'HH:mm:ss.SSSZ”, “yyyy-MM-dd'T'HH:mm:ss.SSS'Z'”, “EEE,dd MMM yyyy HH:mm:ss zzz”, “yyyy-MM-dd”))

jackjson解析框架在解析实体类里面是date数据类型的数据时的默认格式是:UTC类型,即yyyy-MM-dd’T’HH:mm:ss.SSS

并且默认为+8时区,即时间基础上加8小时,

Springboot使用的默认json解析框架是jackjson框架

解决办法一

重写jackson反序列化

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @version 1.0.0
 * @description 重写反序列化
 * @date 2018/12/25 9:51
 **/

public class CustomJsonDateDeserializer extends JsonDeserializer<Date> {
@Override
    public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = jp.getText();
        try {
            return format.parse(date);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
      }
    }

在需要的date属性上添加注解:

@JsonDeserialize(using = CustomJsonDateDeserializer.class)
private Date txnTime;

使用这种方式,需要重写上面反序列化抽象类

解决办法二

使用@JsonFormat注解指定所需的接收格式,不需要重写反序列化:

    //GMT+8表示时区,东八区,需加上时区,shape 默认是JsonFormat.Shape.ANY,
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date txnTime;

解决办法三

如果排除了jackjson框架则使用fastjson注解,不要重写反序列化

@JSONField(format = “yyyy-MM-dd HH:mm:ss”)
private Date txnTime;

需要添加的依赖:

    <!-- fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.32</version>
    </dependency>
    <!-- jackson-->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.6.4</version>
    </dependency>

最后介绍一种全局修改接收时间格式的方式

用MappingJackson2HttpMessageConverter配置在Application.Java启动类,指定接收格式,本人不推荐使用,因为这是全局性的,不是很灵活,因此了解即可

@Bean
    public MappingJackson2HttpMessageConverter getMappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        //设置日期格式
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleDateFormat smt = new SimpleDateFormat("yyyy-MM-dd");
        objectMapper.setDateFormat(smt);
        mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
        //设置中文编码格式
        List<MediaType> list = new ArrayList<MediaType>();
        list.add(MediaType.APPLICATION_JSON_UTF8);
        mappingJackson2HttpMessageConverter.setSupportedMediaTypes(list);
        return mappingJackson2HttpMessageConverter;
    }

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java中的Set接口实现类HashSet和LinkedHashSet详解

    Java中的Set接口实现类HashSet和LinkedHashSet详解

    这篇文章主要介绍了Java中的Set接口实现类HashSet和LinkedHashSet详解,Set接口和java.util.List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格了,需要的朋友可以参考下
    2024-01-01
  • 详解Java中的ThreadLocal

    详解Java中的ThreadLocal

    ThreadLocal是JDK包提供的,它提供线程本地变量,如果创建一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题
    2021-06-06
  • Java 日期与时间API相关用法总结

    Java 日期与时间API相关用法总结

    这篇文章主要介绍了Java 日期与时间API相关用法总结,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下
    2021-02-02
  • 喜大普奔IntelliJ IDEA 可以使用中文了

    喜大普奔IntelliJ IDEA 可以使用中文了

    IntelliJ Idea最大的亮点开始支持中文,很多英语不好的童鞋有福了,今天通过本文给大家分享如何开启中文汉化,通过图文步骤给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-05-05
  • sql于navicat中能运行在mybatis中不能运行的解决方案

    sql于navicat中能运行在mybatis中不能运行的解决方案

    这篇文章主要介绍了sql于navicat中能运行在mybatis中不能运行的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Java synchronized关键字使用方式及特性解析

    Java synchronized关键字使用方式及特性解析

    这篇文章主要介绍了Java synchronized关键字使用方式及特性解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Java8新特性之字符串去重介绍

    Java8新特性之字符串去重介绍

    这篇文章主要介绍了Java8新特性之字符串去重介绍,新的字符串去重特性可以帮助减少应用中String对象的内存占用,目前该特性只适用于G1垃圾收集器,并且默认不被开启,需要的朋友可以参考下
    2014-09-09
  • Spring中BeanFactory与FactoryBean接口的区别详解

    Spring中BeanFactory与FactoryBean接口的区别详解

    这篇文章主要给大家介绍了关于Spring中BeanFactory与FactoryBean接口的区别的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Spring具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-03-03
  • Java如何获取当前时间的小时/分钟(实现方法)

    Java如何获取当前时间的小时/分钟(实现方法)

    文章介绍了Java获取当前时间的小时、分钟等的方法,包括两种常见方法,并鼓励读者继续浏览相关文章,感兴趣的朋友一起看看吧
    2025-02-02
  • Java判断两个集合是否具有交集及如何获得交集详解

    Java判断两个集合是否具有交集及如何获得交集详解

    这篇文章主要给大家介绍了关于Java判断两个集合是否具有交集及如何获得交集的相关资料,文中通过图文以及实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07

最新评论