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

如何为含anyOf字段的JSON Schema生成Java Record对象?

用Java Record结合Jackson实现JSON Schema的anyOf混合类型

核心思路

因为你的数组元素同时支持Mammal对象和纯字符串(Bird),直接用单一类型无法满足,我们可以通过「接口统一类型 + 自定义序列化/反序列化器」的方式,用Java Record实现需求:

  1. 定义统一的AnimalItem接口作为数组元素的类型
  2. 用Record实现Mammal对象和字符串的包装类
  3. 自定义序列化/反序列化器,让字符串包装类在JSON中呈现为纯字符串,而非对象结构

步骤1:定义基础类型

首先创建Mammal Record,对应你的mammal.json结构:

public record Mammal(String species, int averageLifespan) implements AnimalItem {}

然后创建字符串包装的Record,实现统一接口:

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

// 指定序列化器,让这个Record序列化为纯字符串
@JsonSerialize(using = StringAnimalSerializer.class)
public record StringAnimal(String value) implements AnimalItem {}

再定义统一的密封接口(限制实现类范围,避免无关类型混入):

public sealed interface AnimalItem permits Mammal, StringAnimal {}

步骤2:自定义序列化/反序列化器

字符串序列化器(让StringAnimal输出为纯字符串)

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;

public class StringAnimalSerializer extends JsonSerializer<StringAnimal> {
    @Override
    public void serialize(StringAnimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        // 直接写入字符串值,而非对象结构
        gen.writeString(value.value());
    }
}

混合类型反序列化器(自动识别对象/字符串)

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;

public class AnimalItemDeserializer extends JsonDeserializer<AnimalItem> {
    @Override
    public AnimalItem deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node = p.getCodec().readTree(p);
        if (node.isObject()) {
            // 遇到对象时反序列化为Mammal
            return p.getCodec().treeToValue(node, Mammal.class);
        } else if (node.isTextual()) {
            // 遇到字符串时包装为StringAnimal
            return new StringAnimal(node.asText());
        }
        throw new IOException("不支持的AnimalItem类型");
    }
}

步骤3:定义包含数组的顶层Record

在你的animals.json对应的Record中,指定数组元素的反序列化器:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.List;

public record Animals(@JsonDeserialize(contentUsing = AnimalItemDeserializer.class) List<AnimalItem> animals) {}

效果验证

示例JSON输入

{
  "animals": [
    {"species": "Tiger", "averageLifespan": 20},
    "Bald Eagle",
    {"species": "Elephant", "averageLifespan": 60},
    "Penguin"
  ]
}

反序列化后,animals列表中会包含Mammal和StringAnimal实例;序列化时,StringAnimal会输出为纯字符串,完全符合你的JSON Schema要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 11:00:34