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

基于推导的多态:Jackson生成JSON Schema的继承字段问题

基于Jackson推导式多态生成包含继承字段的JSON Schema问题

我正在使用Jackson结合注解从Java类生成JSON及JSON Schema。Java类中有一个抽象类型(如AbstractType)的JSON属性,该属性可使用AbstractType的多个实现类。

目前使用基于推导的多态(@JsonTypeInfo(use = Id.DEDUCTION))生成JSON效果良好,但无法在JSON Schema中展示继承相关的字段。我尝试过以下方向但未解决:

  • 在运行时覆盖JSON属性类(在Schema生成过程中用实现类替换AbstractType)
  • 生成"oneOf"块而非抽象类型字段
  • 寻找开箱即用的配置
  • 考虑替换Jackson为其他工具
  • 在运行时插入正确类型的JSON属性(类似MixIn但添加全新属性,而非仅覆盖注解)

附加代码示例

@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
@JsonSubTypes({
    @JsonSubTypes.Type(value = TypeImpl1.class, name = "type1"),
    @JsonSubTypes.Type(value = TypeImpl2.class, name = "type2")
})
public abstract class AbstractType {
}

public class TypeImpl1 extends AbstractType {
    @JsonProperty("value")
    public Integer value = 10;
}

public class TypeImpl2 extends AbstractType {
    @JsonProperty("text")
    public String text = "test";
}

public class Container {
    @JsonProperty("name")
    public String name = "test";
    @JsonProperty("field")
    public AbstractType field;
}

示例代码与不完整Schema


解决方案思路与示例

1. 自定义Schema生成器扩展

Jackson默认的JSON Schema生成器对推导式多态支持不足,可通过扩展JsonSchemaGenerator处理抽象类型的子类型,生成包含所有实现类的oneOf结构:

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.jsonSchema.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator;
import com.fasterxml.jackson.module.jsonSchema.types.ObjectSchema;
import com.fasterxml.jackson.module.jsonSchema.types.SchemaType;

import java.util.ArrayList;
import java.util.List;

public class PolymorphicSchemaGenerator extends JsonSchemaGenerator {

    public PolymorphicSchemaGenerator(com.fasterxml.jackson.databind.ObjectMapper mapper) {
        super(mapper);
    }

    @Override
    public JsonSchema generateSchema(JavaType type) {
        Class<?> rawType = type.getRawClass();
        JsonSubTypes subTypesAnn = rawType.getAnnotation(JsonSubTypes.class);
        if (rawType.isAbstract() && subTypesAnn != null) {
            ObjectSchema oneOfSchema = new ObjectSchema();
            oneOfSchema.setType(SchemaType.OBJECT);
            List<JsonSchema> subSchemas = new ArrayList<>();
            for (JsonSubTypes.Type subType : subTypesAnn.value()) {
                JavaType subJavaType = _mapper.constructType(subType.value());
                subSchemas.add(super.generateSchema(subJavaType));
            }
            oneOfSchema.setOneOf(subSchemas);
            return oneOfSchema;
        }
        return super.generateSchema(type);
    }
}

使用方式:

ObjectMapper mapper = new ObjectMapper();
PolymorphicSchemaGenerator schemaGenerator = new PolymorphicSchemaGenerator(mapper);
JsonSchema schema = schemaGenerator.generateSchema(Container.class);
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema));

2. 临时切换类型标识生成Schema

生成Schema时通过MixIn将推导式多态临时切换为显式类型标识(Id.NAME),Jackson会自动生成oneOf结构,生成完成后恢复原配置:

// 生成Schema时添加MixIn
mapper.addMixIn(AbstractType.class, AbstractTypeSchemaMixIn.class);
JsonSchemaGenerator generator = new JsonSchemaGenerator(mapper);
JsonSchema schema = generator.generateSchema(Container.class);
// 移除MixIn恢复推导式多态
mapper.removeMixIn(AbstractType.class, AbstractTypeSchemaMixIn.class);

// 定义MixIn类
abstract class AbstractTypeSchemaMixIn {
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
    @JsonSubTypes({
        @JsonSubTypes.Type(value = TypeImpl1.class, name = "type1"),
        @JsonSubTypes.Type(value = TypeImpl2.class, name = "type2")
    })
    public abstract void dummy();
}

3. 升级Jackson版本并启用增强特性

Jackson 2.15及以上版本对推导式多态的Schema生成有了官方支持,升级依赖后启用INCLUDE_POLYMORPHIC_TYPES特性:

JsonSchemaGenerator generator = new JsonSchemaGenerator(mapper);
generator.configure(JsonSchemaGenerator.Feature.INCLUDE_POLYMORPHIC_TYPES, true);
JsonSchema schema = generator.generateSchema(Container.class);

注意:需确保AbstractType上已标注@JsonSubTypes注解,以便生成器识别所有子类型。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 22:35:57