SpringDoc/Swagger如何添加运行时注册的Jackson子类继承信息?
问题描述
当Jackson父类未使用@JsonSubTypes或@Schema(subTypes = ...)注解声明子类时,SpringDoc/Swagger不会生成子类型的Schema。但项目中子类是在启动阶段通过Spring Bean扫描带有@JsonTypeName注解的类,自动注册到Jackson ObjectMapper中的,无法提前给父类添加上述注解。
现有Kotlin代码示例如下:
data class SubtypesRequest(val elements: List<Parent>) @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type" ) @JsonTypeName("parent") open abstract class Parent(val name: String) @JsonTypeName("childX") @Schema(allOf = [Parent::class]) class ChildX(name: String, val x: String) : Parent(name) @JsonTypeName("childY") @Schema(allOf = [Parent::class]) class ChildY(name: String, val y: String) : Parent(name)
此时SpringDoc/Swagger仅生成Parent类型的Schema,列表元素仅指向Parent,但实际业务中需要允许ChildX、ChildY作为列表元素。手动注册Schema的尝试未成功,请问是否可以通过SpringDoc/Swagger API添加该继承关系信息?
解决方案
可以通过SpringDoc提供的扩展API,结合Jackson已注册的子类型信息,动态给父类Schema添加子类型声明,具体实现如下:
步骤1:动态获取Jackson已注册的子类型
通过Spring容器注入的ObjectMapper,利用其内置的类型解析器,提取出父类Parent对应的所有已注册子类型。
步骤2:实现OpenApiCustomizer修改Schema
创建OpenApiCustomizer类型的Bean,在OpenAPI构建完成后,找到Parent对应的Schema,手动添加子类型引用关联。
具体Kotlin代码实现:
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder import io.swagger.v3.oas.models.OpenAPI import io.swagger.v3.oas.models.media.Schema import org.springdoc.core.customizers.OpenApiCustomizer import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration class SpringDocSubtypeConfig { @Bean fun parentSubtypeCustomizer(objectMapper: ObjectMapper): OpenApiCustomizer { return OpenApiCustomizer { openApi: OpenAPI -> // 从Jackson获取Parent已注册的所有子类型 val typeResolver: TypeResolverBuilder<*> = objectMapper.serializationConfig.defaultTyper(null) val subtypes = typeResolver.findSubtypes(Parent::class.java) // 找到OpenAPI中Parent对应的Schema val parentSchema: Schema<*>? = openApi.components.schemas["Parent"] parentSchema?.let { // 给Parent Schema添加子类型引用 val subtypeRefs = subtypes.map { subtype -> Schema<Any>().`$ref`("#/components/schemas/${subtype.simpleName}") } it.subTypes = subtypeRefs } } } }
验证效果
启动项目后,Swagger UI中SubtypesRequest的elements列表将允许选择Parent、ChildX、ChildY三种类型,且每个子类型的专属字段会正确展示。
注意事项
- 确保所有子类已被Spring Bean扫描到,且
@JsonTypeName注解配置正确,Jackson完成子类型注册。 - 如果子类Schema未被自动生成,可通过
SchemaGenerator手动生成并添加到OpenAPI的Components中。
内容的提问来源于stack exchange,提问作者Martin Ahrer
相关产品推荐
相关产品推荐

