如何将LocalDate序列化为指定JSON格式?求标准实现方案
如何用Jackson将LocalDate序列化为特定的嵌套数组JSON格式
我需要把日期序列化为如下强制要求的JSON格式:
{ "element": [ "~#date", [ "2013-05-31" ] ] }
但通过常规POJO数组的方式实现时,得到的是不符合要求的对象结构:
{ "element": [ { "~#date": "2024-09-17" } ] }
我尝试过为LocalDate数组写序列化器,但感觉像是取巧,而且日期数量始终为1。有没有标准的实现方式?
当前实现问题分析
你当前用MyDate类包裹LocalDate[]并加上@JsonProperty,Jackson会默认把这个POJO序列化为键值对对象——这是Jackson处理POJO的默认行为,自然和你想要的数组结构不匹配,所以才会输出{"~#date": "..."}的格式。
标准解决方案:自定义序列化或使用@JsonValue
这种带类型标记的嵌套数组属于自定义结构化JSON,Jackson没有直接的注解支持,但可以通过以下两种标准方式实现,完全不属于取巧:
方案1:用@JsonValue定义序列化输出结构
创建一个专门的类封装这种标记化结构,通过@JsonValue告诉Jackson直接返回我们需要的数组:
@Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor public class TaggedDate { private LocalDate date; private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @JsonValue public Object[] toTaggedArray() { // 构造要求的嵌套数组:["~#date", ["日期字符串"]] return new Object[]{ "~#date", new String[]{date.format(DATE_FORMATTER)} }; } }
然后在主对象中直接使用这个类:
@JsonProperty("element") private TaggedDate element; // 如果是多个日期,用TaggedDate[]即可
序列化后就能得到完全符合要求的格式。
方案2:字段级自定义序列化器
如果不想额外创建类,可以直接给LocalDate字段(或数组)写自定义序列化器,手动生成数组结构:
public class TaggedLocalDateSerializer extends JsonSerializer<LocalDate> { private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @Override public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 手动构建嵌套数组 gen.writeStartArray(); gen.writeString("~#date"); gen.writeStartArray(); gen.writeString(value.format(DATE_FORMATTER)); gen.writeEndArray(); gen.writeEndArray(); } }
然后在主对象的字段上应用这个序列化器:
@JsonProperty("element") @JsonSerialize(using = TaggedLocalDateSerializer.class) private LocalDate aDate;
如果是多个日期(数组),可以调整序列化器为处理LocalDate[]:
public class TaggedLocalDateArraySerializer extends JsonSerializer<LocalDate[]> { private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @Override public void serialize(LocalDate[] values, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeStartArray(); for (LocalDate date : values) { gen.writeStartArray(); gen.writeString("~#date"); gen.writeStartArray(); gen.writeString(date.format(DATE_FORMATTER)); gen.writeEndArray(); gen.writeEndArray(); } gen.writeEndArray(); } }
对应的字段注解:
@JsonProperty("element") @JsonSerialize(using = TaggedLocalDateArraySerializer.class) private LocalDate[] aDates;
为什么这不是取巧?
Jackson的核心设计就是支持自定义序列化/反序列化来处理非标准JSON格式,这种带类型标记的数组结构不属于JSON的常规键值对规范,因此使用自定义序列化器或@JsonValue是完全标准的解决方案,而非取巧。
内容的提问来源于stack exchange,提问作者tm1701
相关产品推荐
相关产品推荐

