Spring REST接口返回LocalDateTime报错原因及解决方法
问题分析与解决方案
异常原因
这个报错的核心问题是Jackson默认没有正确处理Java 8的LocalDateTime类型的序列化与反序列化:
- 后端Spring控制器返回
LocalDateTime时,默认的Jackson配置会把它序列化成一个包含year、month、dayOfMonth等字段的JSON对象(比如{"year":2024,"month":5,...})。 - 但客户端用
restTemplate.getForEntity(url, LocalDateTime.class)请求时,Jackson期望接收的是符合ISO-8601标准的字符串(比如"2024-05-20T15:30:00")或者数组格式,实际收到的是JSON对象,就会抛出MismatchedInputException,提示"Expected array or string"。
解决方法
下面分后端和客户端两部分给出具体解决方案:
1. 后端Spring配置(关键)
首先要确保项目中包含Jackson处理Java 8时间类型的依赖:
- 如果是Spring Boot项目,
spring-boot-starter-web已经内置了jackson-datatype-jsr310,无需额外添加。 - 如果是普通Spring项目,需要在pom.xml(Maven)中添加:
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> <version>你的Jackson版本</version> </dependency>
然后配置Jackson将LocalDateTime序列化为ISO-8601字符串:
方式一:通过配置文件(Spring Boot)
在application.properties或application.yml中添加:
# 禁用时间戳序列化,转为字符串格式 spring.jackson.serialization.write-dates-as-timestamps=false # 指定日期时间格式(可选,默认就是ISO-8601) spring.jackson.date-format=yyyy-MM-dd'T'HH:mm:ss
方式二:自定义ObjectMapper Bean
如果需要更灵活的配置,可以手动注册JavaTimeModule:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); // 注册Java 8时间模块 objectMapper.registerModule(new JavaTimeModule()); // 禁用时间戳,输出字符串格式 objectMapper.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); return objectMapper; } }
方式三:局部字段/方法注解
如果只想给这个特定端点配置,可以在返回方法上添加@JsonFormat注解:
import com.fasterxml.jackson.annotation.JsonFormat; import java.time.LocalDateTime; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class YourController { @GetMapping(path = "/lastDateTimeOfReset") @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") LocalDateTime fetchLastDateTimeOfReset() { return mongoManagerService.fetchLastDateTimeOfReset(); } }
2. 客户端RestTemplate配置
客户端的RestTemplate也需要支持LocalDateTime的反序列化,确保它的消息转换器包含JavaTimeModule:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.client.RestTemplate; // 配置RestTemplate RestTemplate restTemplate = new RestTemplate(); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(new JavaTimeModule()); objectMapper.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); converter.setObjectMapper(objectMapper); restTemplate.getMessageConverters().removeIf(m -> m instanceof MappingJackson2HttpMessageConverter); restTemplate.getMessageConverters().add(converter); // 之后正常请求 ResponseEntity<LocalDateTime> lastDateEntity = restTemplate.getForEntity(url, LocalDateTime.class);
这样配置后,后端会返回标准的ISO-8601日期字符串,客户端也能正确解析成LocalDateTime对象,异常就会消失。
内容的提问来源于stack exchange,提问作者Rotem Linik
相关产品推荐
相关产品推荐

