Spring Boot 4.x 升级到 Jackson 3.x 后,部分配置项名称和用法发生了变化。本文将介绍如何配置 Jackson 序列化 LocalDateTime。
依赖修改
1
2
3
4
5
6
7
8
9
10
11
|
<!-- Spring Boot 3.x -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Spring Boot 4.x -->
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
|
Jackson 序列化 LocalDate 和 LocalDateTime
Spring Boot 3
Jackson 2 时使用如下方式序列化 LocalDate、LocalDateTime:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.format.DateTimeFormatter;
@Configuration
public class JacksonConfig {
private final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
return builder -> {
builder.serializers(
new LocalDateTimeSerializer(DATE_TIME_FORMAT),
new LocalDateSerializer(DATE_FORMAT));
builder.deserializers(
new LocalDateTimeDeserializer(DATE_TIME_FORMAT),
new LocalDateDeserializer(DATE_FORMAT));
};
}
}
|
Spring Boot 4
来到 Jackson 3 以后,序列化 LocalDate 和 LocalDateTime 的方式发生了变化,需要使用新的类和方法进行配置,有两种方式实现(其他类型同理):
方式一
基于 SimpleModule 实现相应类的 Serializer 和 Deserializer。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tools.jackson.databind.DeserializationFeature;
import tools.jackson.databind.cfg.DateTimeFeature;
import tools.jackson.databind.ext.javatime.deser.LocalDateDeserializer;
import tools.jackson.databind.ext.javatime.deser.LocalDateTimeDeserializer;
import tools.jackson.databind.ext.javatime.ser.LocalDateSerializer;
import tools.jackson.databind.ext.javatime.ser.LocalDateTimeSerializer;import tools.jackson.databind.module.SimpleModule;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
public class JacksonConfig {
private static final String DATE_FORMAT = "yyyy-MM-dd";
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
@Bean
public JsonMapperBuilderCustomizer jacksonCustomizer() {
// LocalDateTime
LocalDateTimeSerializer localDateTimeSerializer = new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT));
LocalDateTimeDeserializer localDateTimeDeserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT));
// LocalDate
LocalDateSerializer localDateSerializer = new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_FORMAT));
LocalDateDeserializer localDateDeserializer = new LocalDateDeserializer(DateTimeFormatter.ofPattern(DATE_FORMAT));
SimpleModule module = new SimpleModule("TOFUWINE-WORKBENCH-MODULE");
module.addDeserializer(LocalDateTime.class, localDateTimeDeserializer)
.addSerializer(LocalDateTime.class, localDateTimeSerializer)
.addDeserializer(LocalDate.class, localDateDeserializer)
.addSerializer(LocalDate.class, localDateSerializer);
return builder -> {
builder.enable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
.addModule(module)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); // 忽略未知字段 (避免版本升级等原因导致反序列化失败)
};
}
}
|
方式二
基于 config override 实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tools.jackson.databind.DeserializationFeature;
import tools.jackson.databind.cfg.DateTimeFeature;
import tools.jackson.databind.ext.javatime.deser.LocalDateDeserializer;
import tools.jackson.databind.ext.javatime.deser.LocalDateTimeDeserializer;
import tools.jackson.databind.ext.javatime.ser.LocalDateSerializer;
import tools.jackson.databind.ext.javatime.ser.LocalDateTimeSerializer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
public class JacksonConfig {
private static final String DATE_FORMAT = "yyyy-MM-dd";
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
@Bean
public JsonMapperBuilderCustomizer jacksonCustomizer() {
return builder -> {
builder.enable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS) // DATE 转时间戳
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) // 忽略未知字段 (避免版本升级等原因导致反序列化失败)
.withConfigOverride(LocalDateTime.class,
time -> time.setFormat(JsonFormat.Value.forPattern(DATE_TIME_FORMAT)))
.withConfigOverride(LocalDate.class,
date -> date.setFormat(JsonFormat.Value.forPattern(DATE_FORMAT)));
};
}
}
|
注意:JsonFormat 仍是 com.fasterxml.jackson 包下的。这是因为 Jackson 3.x 将不再包含独立的注解模块,而是继续使用 2.x 的模块。
1
2
3
4
5
|
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version.annotations}</version>
</dependency>
|
如果有其他类型希望自定义实现序列化/反序列化,均可以参考上述方式实现。
参考网站