如何用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
相关产品推荐
相关产品推荐

