SpringBoot 使用 Jackson 处理 Java8 时间 API

SpringBoot 使用 Jackson 处理 Java8 时间 API

场景

在项目中的实体类里面使用了 Java8 新的时间 API,例如 LocalDate, LocalTime, LocalDateTime 等。然而在将这些时间类型的字段序列化返回到前端时,但格式却感觉有些异常。

嗯,大概就是下面这种样子的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"dayOfMonth": 27,
"dayOfWeek": "MONDAY",
"dayOfYear": 239,
"month": "AUGUST",
"monthValue": 8,
"year": 2018,
"hour": 10,
"minute": 0,
"nano": 370000000,
"second": 52,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
}

这是什么鬼的格式。。。

解决方案

添加依赖

1
2
3
4
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

修改 application.yml,配置 spring.jackson.serialization.write_dates_as_timestamps 禁用 打印日期为时间戳的功能

1
2
3
4
spring:
jackson:
serialization:
write_dates_as_timestamps: false

如此,在返回数据到前端的时候 SpringBoot 就会自动将日期格式化为 yyyy-MM-ddThh:mm:ss

然而,如果我们想要在程序中手动的序列化日期怎么办呢?实际上也很简单,使用代码 .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) 来禁止序列化时间为时间戳并注册 jackson-datatype-jsr310 中的 JavaTimeModule 模块。

下面是吾辈在项目里使用的一个全局 ObjectMapper 对象

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
/**
* 提供一个全局可用的序列化 Bean
*/
public static final ObjectMapper OM = new ObjectMapper()
//Date 对象的格式
.setDateFormat(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"))
//禁止序列化值为 null 的属性
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
//禁止序列化时间为时间戳
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.registerModules(
//注册 Jsr310(Java8 的时间兼容模块)
new JavaTimeModule(),
//序列化 Long 为 String
new SimpleModule()
//大数字直接序列化为 String
.addSerializer(Long.class, ToStringSerializer.instance)
.addSerializer(Long.TYPE, ToStringSerializer.instance)
.addSerializer(long.class, ToStringSerializer.instance)
.addSerializer(BigInteger.class, ToStringSerializer.instance)
//大浮点数直接序列化为 String
.addSerializer(BigDecimal.class, new JsonSerializer<BigDecimal>() {
@Override
public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(value.setScale(10, BigDecimal.ROUND_HALF_UP).toPlainString());
}
})
)
//JSON 序列化移除 transient 修饰的 Page 无关紧要的返回属性(Mybatis Plus)
.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);

那么,以上就是 SpringBoot 序列化 Java8 时间 API 的问题和解决方案啦 ヾ(@^▽^@)ノ