如何使用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多态的限制:
- 自定义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); } }
- 给Schema接口指定反序列化器:
@JsonDeserialize(using = SchemaDeserializer.class) public interface Schema {}
你之前在BuiltinSchema上配置的按type字段匹配的多态注解可以完全保留不用修改。
内容的提问来源于stack exchange,提问作者CidTori
相关产品推荐
相关产品推荐

