Spring Boot中使用@RequestBody对json解析时,LocalDateTime反序列化失败

场景描述

  • 需求
需求主要是将前端通过json传上来的时间,通过@RequestBody自动绑定到Bean里的LocalDateTime成员上。
  • 绑定方法
使用@JsonFormat 注解,示例:@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
  • 出现问题的版本

我使用Spring Boot 2.0.0 时,直接在字段上加上@JsonFormat 注解就可以完成数据的绑定。

而在使用Spring Boot 1.5.8时,只在字段上加上@JsonFormat 注解,在数据绑定时就会报错。

  • 报错信息
        w.s.m.s.DefaultHandlerExceptionResolver : 
        Failed to read HTTP message: 
            org.springframework.http.converter.HttpMessageNotReadableException: 
                JSON parse error: 
                    Can not construct instance of java.time.LocalDateTime: 
                        no String-argument constructor/factory method to deserialize from String value ('2018-04-12 14:00:16'); 
                            nested exception is com.fasterxml.jackson.databind.JsonMappingException: 
                                Can not construct instance of java.time.LocalDateTime: 
                                    no String-argument constructor/factory method to deserialize from String value ('2018-04-12 14:00:16')
    at [Source: java.io.PushbackInputStream@5cf71c5b; line: 9, column: 17] 
        (through reference chain: 
            com.semonx.gateway.comm.entity.ErrCodePushVo["errcodepushList"]
                ->java.util.ArrayList[0]
                    ->com.semonx.gateway.comm.entity.ErrCodePushSon["happentime"])

解决方法

添加Jackson对Java Time的支持后,就能解决这个问题。

在pom.xml中添加:

<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-parameter-names</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

添加JavaConfig,自动扫描新添加的模块:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.fasterxml.jackson.databind.ObjectMapper;

@Configuration
public class JacksonConfig {

    @Bean
    public ObjectMapper serializingObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.findAndRegisterModules();
        return objectMapper;
    }
}

或者在application.properties添加如下配置:
spring.jackson.serialization.write-dates-as-timestamps=false

或者只注册JavaTimeModule,添加下面的Bean

@Bean
public ObjectMapper serializingObjectMapper() {
  ObjectMapper objectMapper = new ObjectMapper();
  objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
  objectMapper.registerModule(new JavaTimeModule());
  return objectMapper;
}

参考资料

新的Jackson模块:https://github.com/FasterXML/jackson-modules-java8

其他人遇到的类似的情况:http://www.jb51.net/article/136389.htm

上一篇:单例模式


下一篇:Java8日期/时间使用