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

如何将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 09:36:01