结论
对于 Java 8 的日期时间类型,如 LocalDateTime,全局的 spring.jackson.date-format 属性并不适用,因为这些类型通常需要特定的序列化器来格式化。需要添加配置类来添加对LocalDateTime的支持。
问题
VO的属性有一个创建时间和一个更新时间。
public class xxVO implements Serializable {
private static final long serialVersionUID = 1L;
private LocalDateTime createAt;
private LocalDateTime updateAt;
}
yaml中添加了日期序列化格式为yyyy-MM-dd HH:mm:ss。
jackson:
default-property-inclusion: non_null
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Shanghai
但是从返回结果来看并没有生效。
{
"createAt": "2024-06-01T09:38:17",
"updateAt": "2024-06-01T15:11:43"
}
解决方案
- 引入依赖
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.13.0</version>
</dependency>
配置ObjectMapper
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
return mapper;
}
}
但是这种方式会导致yaml中的配置不生效。比如我的配置中设置了时区和对null值的处理,都需要一一在ObjectMapper中配置,非常麻烦。
然后想到可不可以通过修改框架里的ObjectMapper来达到这个目的。
@Component
public class ObjectMapperCustomizer implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ObjectMapper mapper = event.getApplicationContext().getBean(ObjectMapper.class);
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
mapper.registerModule(module);
}
}
这里我们监听ContextRefreshedEvent事件,然后从ApplicationContext中直接获取ObjectMapper。通过debug测试,确实拿到了ObjectMapper的Bean对象,也设置了值但是并没有生效(知道原因的同学欢迎在评论区指出)。
配置Module
后来在一篇博客(底部有链接)中看到了这个问题的另一个解决方案,试了一下生效了,配置如下。
@Configuration
public class JacksonConfig {
@Value("${spring.jackson.date-format:'yyyy-MM-dd HH:mm:ss'}")
private String pattern;
@Bean
public Module javaTimeModule() {
JavaTimeModule module = new JavaTimeModule();
// 为 LocalDateTime 设置自定义序列化器
LocalDateTimeSerializer localDateTimeSerializer = new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));
LocalDateTimeDeserializer localDateTimeDeserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(pattern));
module.addSerializer(LocalDateTime.class, localDateTimeSerializer);
module.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);
return module;
}
}
这个配置可以和jackson的yaml配置一块生效。我的yaml配置还可以继续使用,还新增了对LocalDataTime的支持,完美。
引用
https://www.51cto.com/article/777079.html