在SpringBoot 中使用LocalDateTime 时,接口报错
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.time.LocalDateTime` from String "2008-11-10 07:13:16": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2008-11-10 07:13:16' could not be parsed at index 10; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDateTime` from String "2008-11-10 07:13:16": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2008-11-10 07:13:16' could not be parsed at index 10
默认情况下,Jackson(Spring Boot使用的JSON处理器)期望的日期时间格式是ISO 8601格式(例如:2008-11-10T07:13:16),而不是带有空格和没有’T’字符分隔日期和时间的格式。
方法0:配置文件
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
这种方式主要用于旧版的java.util.Date
和java.sql.Time
等类型的格式化。对于 LocalDateTime
无效
方法 1: 修改输入数据格式
确保输入的日期时间字符串符合ISO 8601标准,例如:“2008-11-10T07:13:16”,但是很显然,这种方法通常是不会使用的
方法 2:使用@JsonFormat 注解
直接在实体类的相应字段上标记@JsonFormat
注解
public class YourEntityClass {
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime dateTimeField;
// getter and setter
}
这种方法非常快,但在大量实体使用了LocalDateTime
时,需要在所有实体上分别进行处理,在这种情况下,我们一般希望进行全局处理,而不是一个个标记。
方法 3:自定义ObjectMapper配置
可以配置Spring Boot中的Jackson ObjectMapper来接受并解析不同的日期格式。
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(javaTimeModule);
return objectMapper;
}
}
在这种方法中,我们用自定义的ObjectMapper
bean 覆盖了系统默认的ObjectMapper
。这可能产生额外的担忧,默认的ObjectMapper
是否含有一些默认配置,是我们自定义的ObjectMapper
bean 所没配置的?这里需要深入研究一下。
方法 4:Jackson2ObjectMapperBuilderCustomizer
这种方法允许你在不直接创建ObjectMapper
Bean的情况下对ObjectMapper
进行自定义,适合用于添加模块、序列化器、反序列化器等操作。
@Configuration
public class JacksonConfig implements Jackson2ObjectMapperBuilderCustomizer {
@Override
public void customize(org.springframework.http.converter.json.Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
JavaTimeModule module = new JavaTimeModule();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
jacksonObjectMapperBuilder.modules(module);
}
}
或者定义Jackson2ObjectMapperBuilderCustomizer Bean
@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> {
JavaTimeModule module = new JavaTimeModule();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
builder.modules(module);
};
}
}
方法 5:定义Jackson2ObjectMapperBuilder Bean
你可以通过创建一个Jackson2ObjectMapperBuilder类型的Bean来实现全局配置。这样做的好处是能够集中处理所有需要自定义的Jackson配置,包括但不限于日期格式的设定。
@Configuration
public class JacksonGlobalConfig {
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
JavaTimeModule module = new JavaTimeModule();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 添加LocalDateTime的序列化器
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
// 如果需要,还可以添加其他类型的序列化器或反序列化器
return new Jackson2ObjectMapperBuilder()
.modules(module)
// 你可以在这里添加更多的配置选项
;
}
}
方法 6:实现WebMvcConfigurer接口
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
ObjectMapper objectMapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
// 添加JavaTimeModule并设置LocalDateTime的序列化格式
JavaTimeModule javaTimeModule = new JavaTimeModule();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
objectMapper.registerModule(javaTimeModule);
}
}
}
}