You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Jackson将LocalDateTime序列化为旧格式(兼容库升级场景)

升级Jackson后LocalDateTime序列化格式从嵌套对象变为数组的解决方法

升级Jackson到2.12.6系列后,使用Json.toJSON(LocalDateTime.now())(内部调用ObjectMapper.valueToTree(data))序列化LocalDateTime时,输出格式发生了变化:

原序列化格式(嵌套对象)

"date": {
    "year": 2022,
    "month": "SEPTEMBER",
    "dayOfMonth": 8,
    "dayOfWeek": "THURSDAY",
    "dayOfYear": 251,
    "monthValue": 9,
    "hour": 16,
    "minute": 4,
    "second": 30,
    "nano": 0,
    "chronology": {
        "calendarType": "iso8601",
        "id": "ISO"
    }
}

新序列化格式(数组)

[2022,9,20,11,28,9,598000000]

尝试过直接调用ObjectMapper.writeValueAsString、注册JSR310Module等方式,均无法恢复旧格式。由于项目基于Play框架+SBT编译,新增模块依赖必须升级Jackson,且不想修改全项目代码,最终通过自定义序列化器解决问题。

解决步骤

1. 自定义LocalDateTime序列化器

创建LocalDateTimeKeySerializer类,手动构建旧格式的嵌套对象结构:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.TextStyle;
import java.util.Locale;

public class LocalDateTimeKeySerializer extends StdSerializer<LocalDateTime> {

    public LocalDateTimeKeySerializer() {
        super(LocalDateTime.class);
    }

    @Override
    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        gen.writeNumberField("year", value.getYear());
        gen.writeStringField("month", value.getMonth().getDisplayName(TextStyle.FULL, Locale.ENGLISH));
        gen.writeNumberField("dayOfMonth", value.getDayOfMonth());
        gen.writeStringField("dayOfWeek", value.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH));
        gen.writeNumberField("dayOfYear", value.getDayOfYear());
        gen.writeNumberField("monthValue", value.getMonthValue());
        gen.writeNumberField("hour", value.getHour());
        gen.writeNumberField("minute", value.getMinute());
        gen.writeNumberField("second", value.getSecond());
        gen.writeNumberField("nano", value.getNano());
        
        gen.writeObjectFieldStart("chronology");
        gen.writeStringField("calendarType", "iso8601");
        gen.writeStringField("id", "ISO");
        gen.writeEndObject();
        
        gen.writeEndObject();
    }
}

2. 注册自定义序列化器到Jackson模块

编写JsonCustomModule模块,注册上述序列化器:

import com.fasterxml.jackson.databind.module.SimpleModule;

public class JsonCustomModule extends SimpleModule {

    public JsonCustomModule() {
        addSerializer(LocalDateTime.class, new LocalDateTimeKeySerializer());
    }
}

3. 在Play框架中启用自定义模块

在项目初始化或配置类中,获取Play框架的ObjectMapper并注册自定义模块:

import com.fasterxml.jackson.databind.ObjectMapper;
import play.libs.Json;

// 初始化时执行
ObjectMapper mapper = Json.mapper();
mapper.registerModule(new JsonCustomModule());

这样就能让LocalDateTime序列化后恢复为原有的嵌套对象格式,无需修改项目中所有调用序列化的代码。

内容的提问来源于stack exchange,提问作者Charnel92

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 23:10:55