问题描述
jackson处理LocalDateTime序列化的时候报错
ObjectMapper mapper = new ObjectMapper();
mapper.writeValueAsString(LocalDateTime.now());
报错信息
com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Java 8 date/time type `java.time.OffsetDateTime` not supported by default:
add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling
如果处理Date对象是不会报错的
ObjectMapper mapper = new ObjectMapper();
mapper.writeValueAsString(new Date());
// 1684480558531
解决方法
按照异常信息提示,引入模块com.fasterxml.jackson.datatype:jackson-datatype-jsr310
引入依赖
<!-- json -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.13.4</version>
</dependency>
注册JavaTimeModule
ObjectMapper mapper = new ObjectMapper();
// 已过时
// mapper.registerModule(new JSR310Module());
// Jackson 2.7 之后使用JavaTimeModule
mapper.registerModule(new JavaTimeModule());
// 默认输出
mapper.writeValueAsString(LocalDateTime.now())
[2023,5,19,15,21,57,337000000]
发现输出的格式不太对,进一步优化
ObjectMapper mapper = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule();
// 设置序列化格式
javaTimeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
mapper.registerModule(javaTimeModule);
try {
System.out.println(mapper.writeValueAsString(LocalDateTime.now()));
// "2023-05-19 15:29:01"
} catch (JsonProcessingException e) {
e.printStackTrace();
}
完整测试代码
package com.example.demo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class JsonTest {
@Test
public void testJavaTimeModule() {
ObjectMapper mapper = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule();
// 设置序列化格式
javaTimeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
mapper.registerModule(javaTimeModule);
try {
System.out.println(mapper.writeValueAsString(LocalDateTime.now()));
// "2023-05-19 15:29:01"
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
如果确实不生效,可以临时修改单个字段的序列化方式
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "Asia/Shanghai")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime updateTime;
自己出现的坑
由于线上生产环境还多了一个数据加密的拦截,拦截前会将数据先进行序列化,此时并没有走统一的序列化,导致线上一直提示序列化失败,而开发环境是可以的,一度认为是配置错了,或者是打包结果不对导致的
最终排查发现是数据加密拦截器中数据序列化没有走配置好的序列化方式