基于推导的多态: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; }

解决方案思路与示例
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
相关产品推荐
相关产品推荐

