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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 15:52:18