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

如何使用Jackson反序列化JSON Schema并正确处理$ref字段?

方案1:平级注册所有子类型,避免多级多态限制

你之前使用DEDUCTION失效的核心原因是将BuiltinSchema作为中间层级注册到子类型,触发了Jackson多级多态不支持的问题。你可以直接把所有Schema实现类平级注册到Schema接口的子类型列表中,去掉BuiltinSchema接口上的多态注解即可:

// 只在顶级Schema接口配置多态推导
@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
@JsonSubTypes({
        @Type(value = ReferencedSchema.class),
        // 直接注册所有内置Schema实现,不再经过BuiltinSchema中间层
        @Type(value = ObjectSchema.class),
        @Type(value = ArraySchema.class),
        @Type(value = StringSchema.class),
        @Type(value = IntegerSchema.class),
        @Type(value = NumberSchema.class)
})
public interface Schema {}

// BuiltinSchema上的@JsonTypeInfo、@JsonSubTypes注解全部删除
public interface BuiltinSchema extends Schema {}

Jackson的属性推导逻辑会优先匹配有$ref字段的ReferencedSchema,剩余有type字段的结构会自动匹配对应类型的内置Schema,完全符合JSON Schema的规范要求。


方案2:自定义反序列化器,完全可控的匹配逻辑

如果你需要保留BuiltinSchema的层级结构,或者后续要扩展更多Schema规则(比如支持布尔类型的Schema),可以直接自定义反序列化器实现匹配逻辑,彻底绕开Jackson多态的限制:

  1. 自定义Schema反序列化器:
public class SchemaDeserializer extends StdDeserializer<Schema> {
    public SchemaDeserializer() {
        super(Schema.class);
    }

    @Override
    public Schema deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node = p.getCodec().readTree(p);
        // 按照JSON Schema规范优先判断$ref字段
        if (node.has("$ref")) {
            return p.getCodec().treeToValue(node, ReferencedSchema.class);
        }
        // 无$ref时走内置类型的反序列化逻辑
        return p.getCodec().treeToValue(node, BuiltinSchema.class);
    }
}
  1. 给Schema接口指定反序列化器:
@JsonDeserialize(using = SchemaDeserializer.class)
public interface Schema {}

你之前在BuiltinSchema上配置的按type字段匹配的多态注解可以完全保留不用修改。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:00:02