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

如何为使用Jackson接口多态的请求体字段配置Springdoc Schema

如何为使用Jackson接口多态的请求体字段配置Springdoc Schema

我之前在项目里要实现Jackson多态请求体的Swagger文档展示,踩了好几个坑,现在把我整理的可行方案分享给你。首先先看看我用的相关依赖配置(build.gradle里的),这些版本搭配起来稳定性不错:

implementation("org.springframework.boot:spring-boot-starter-web:2.7.18")
implementation("org.springdoc:springdoc-openapi-ui:1.8.0") {
    exclude(group = "org.slf4j", module = "slf4j-api")
}
implementation("org.springdoc:springdoc-openapi-webmvc-core:1.8.0") {
    exclude(group = "org.slf4j", module = "slf4j-api")
}

之所以排除slf4j-api,是因为Spring Boot的starter已经自带了这个依赖,不排除的话容易出现版本冲突问题。

1. 先配置Jackson的多态注解

首先得给你的父接口/类加上Jackson的多态识别注解,这样Jackson才能根据指定的字段区分不同的子类型。举个实际的例子,比如我定义了一个Animal父接口,还有Cat和Dog两个子类:

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type" // 这个字段用来区分子类型,前端传参时要带上
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Cat.class, name = "cat"),
    @JsonSubTypes.Type(value = Dog.class, name = "dog")
})
public interface Animal {
    String getSound();
}

public class Cat implements Animal {
    private String sound = "meow";
    private String favoriteToy; // Cat特有的字段

    // 这里记得加getter和setter,或者用Lombok的@Data注解
}

public class Dog implements Animal {
    private String sound = "woof";
    private Boolean isGuardDog; // Dog特有的字段

    // getter和setter
}

2. 配置Springdoc识别多态Schema

这一步是关键,要让Springdoc生成的Swagger文档里能正确展示多态类型的可选结构,以及区分用的type字段。有三种常用方式,你可以按需选:

方式一:在Controller的请求体参数上直接指定

这种方式适合单个接口的场景,直接在@RequestBody参数上用@Schema的oneOf属性指定所有子类型:

@PostMapping("/pets")
public ResponseEntity<String> addPet(
    @RequestBody @Schema(oneOf = {Cat.class, Dog.class}) Animal animal
) {
    // 这里写你的业务逻辑,比如存数据库或者处理请求
    return ResponseEntity.ok("Added pet that says: " + animal.getSound());
}

方式二:全局配置(用OpenApiCustomizer)

如果你的项目里有很多地方用到这个多态类型,不想每个Controller都写一遍,可以用全局配置类来统一注册:

@Configuration
public class SpringdocPolymorphismConfig {

    @Bean
    public OpenApiCustomizer openApiCustomizer() {
        return openApi -> {
            // 先拿到父类型的Schema
            Schema<?> animalSchema = openApi.getComponents().getSchemas().get("Animal");
            if (animalSchema != null) {
                // 设置oneOf属性,指定所有子类型的引用
                animalSchema.setOneOf(List.of(
                    new Schema().$ref("#/components/schemas/Cat"),
                    new Schema().$ref("#/components/schemas/Dog")
                ));
                // 配置discriminator,对应Jackson里的type字段
                Discriminator discriminator = new Discriminator()
                    .propertyName("type")
                    .mapping(Map.of(
                        "cat", "#/components/schemas/Cat",
                        "dog", "#/components/schemas/Dog"
                    ));
                animalSchema.setDiscriminator(discriminator);
            }
        };
    }
}

方式三:直接在父接口上添加@Schema注解

这种方式最直观,把多态的Schema配置直接和Jackson的注解放在一起,维护起来更方便:

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type"
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Cat.class, name = "cat"),
    @JsonSubTypes.Type(value = Dog.class, name = "dog")
})
@Schema(
    oneOf = {Cat.class, Dog.class},
    discriminator = @Discriminator(
        propertyName = "type",
        mapping = {
            @DiscriminatorMapping(value = "cat", schema = Cat.class),
            @DiscriminatorMapping(value = "dog", schema = Dog.class)
        }
    )
)
public interface Animal {
    String getSound();
}

最后提几个要注意的点

  • 一定要保证Spring Boot和Springdoc的版本兼容,我用的2.7.18的Spring Boot搭配1.8.0的Springdoc是经过验证没问题的,如果用更高版本的Spring Boot(比如3.x),要对应升级Springdoc到2.x版本
  • 排除slf4j-api是为了避免依赖冲突,如果你项目里的日志依赖版本和Springdoc自带的不一样,很可能会出问题
  • 测试的时候记得打开Swagger UI(默认地址是/swagger-ui.html),看看请求体的Schema是不是正确展示了所有子类型的字段,以及type下拉选项

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 12:49:37