OpenApi - 有没有办法在使用 springdoc-openapi-maven-plugin 生成的合同中使用带有鉴别器部分的组合模式?

Posted

技术标签:

【中文标题】OpenApi - 有没有办法在使用 springdoc-openapi-maven-plugin 生成的合同中使用带有鉴别器部分的组合模式?【英文标题】:OpenApi - Is there a way to have a ComposedSchema with a discriminator part in a contract generated with springdoc-openapi-maven-plugin? 【发布时间】:2020-10-19 05:31:01 【问题描述】:

我有一个具有以下特性的示例 SpringBoot API:

1 个控制器,它公开一个可通过 GET 请求调用的端点并返回一个自定义类(在我的示例中为 ContainerClass) ContainerClass 包含一个属性 List ParentClass 是一个抽象类,它有 2 个子类:ChildA 和 ChildB

我尝试使用 springdoc-openapi-maven-plugin 从此 API 生成 OpenApi 合约。

在我的 pom.xml 中,我有以下元素:

SpringBoot 版本:2.2.6 org.springdoc:springdoc-openapi-ui:1.4.1 org.springdoc:springdoc-openapi-maven-plugin:1.0

这是我从中生成架构的类。

import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;

public class ContainerClass 

    @ArraySchema(
        arraySchema = @Schema(discriminatorProperty = "classType"), 
        schema = @Schema(implementation = ParentClass.class)
    )
    public List<ParentClass> elements;
    
    // + Getter/Setter

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXISTING_PROPERTY,
        property = "classType",
        defaultImpl = ParentClass.class,
        visible = true)
@JsonSubTypes(
        @JsonSubTypes.Type(value = ChildA.class, name = "CHILD_A"),
        @JsonSubTypes.Type(value = ChildB.class, name = "CHILD_B"))
@Schema(
        description = "Parent description",
        discriminatorProperty = "classType",
        discriminatorMapping = 
                @DiscriminatorMapping(value = "CHILD_A", schema = ChildA.class),
                @DiscriminatorMapping(value = "CHILD_B", schema = ChildB.class)
        
)
public abstract class ParentClass 

    public String classType;

    // + Getter/Setter

@io.swagger.v3.oas.annotations.media.Schema(description = " Child A", allOf = ParentClass.class)
public class ChildA extends ParentClass

@io.swagger.v3.oas.annotations.media.Schema(description = " Child B", allOf = ParentClass.class)
public class ChildB extends ParentClass

当我运行 springdoc-openapi-maven-plugin 时,我得到以下合约文件。

openapi: 3.0.1
info:
  title: OpenAPI definition
  version: v0
servers:
- url: http://localhost:8080
  description: Generated server url
paths:
  /container:
    get:
      tags:
      - hello-controller
      operationId: listElements
      responses:
        "200":
          description: OK
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/ContainerClass'
components:
  schemas:
    ChildA:
      type: object
      description: ' Child A'
      allOf:
      - $ref: '#/components/schemas/ParentClass'
    ChildB:
      type: object
      description: ' Child B'
      allOf:
      - $ref: '#/components/schemas/ParentClass'
    ContainerClass:
      type: object
      properties:
        elements:
          type: array
          description: array schema description
          items:
            oneOf:
            - $ref: '#/components/schemas/ChildA'
            - $ref: '#/components/schemas/ChildB'
    ParentClass:
      type: object
      properties:
        classType:
          type: string
      description: Parent description
      discriminator:
        propertyName: classType
        mapping:
          CHILD_A: '#/components/schemas/ChildA'
          CHILD_B: '#/components/schemas/ChildB'

实际上,在我的上下文中,为了不对现有消费者进行任何重大更改,我需要 ContainerClass 架构中的 items 属性来包含 discriminator 部分包含在 ParentClass 架构中,如下所示:

ContainerClass:
  type: object
  properties:
    elements:
      type: array
      description: array schema description
      items:
        discriminator:
          propertyName: classType
          mapping:
            CHILD_A: '#/components/schemas/ChildA'
            CHILD_B: '#/components/schemas/ChildB'
        oneOf:
        - $ref: '#/components/schemas/ChildA'
        - $ref: '#/components/schemas/ChildB'

当我尝试在注释中设置属性时,我无法做到这一点。当我调试 io.swagger.v3.core.jackson.ModelResolver 的代码时,我无法找到解决方法。 到目前为止,我还没有找到对我有帮助的代码示例。

有没有办法让 ComposedSchema(在我的例子中包含在 ContainerClass 中的数组)具有由 springdoc-openapi-maven-plugin 生成的 disciminator 部分 执行?

【问题讨论】:

【参考方案1】:

这是我通过定义 OpenApiCustomiser Bean 的解决方案:

@Bean
    public OpenApiCustomiser myCustomiser() 

        Map<String, String> classTypeMapping = Map.ofEntries(
                new AbstractMap.SimpleEntry<String, String>("CHILD_A", "#/components/schemas/ChildA"),
                new AbstractMap.SimpleEntry<String, String>("CHILD_B", "#/components/schemas/ChildB")
        );

        Discriminator classTypeDiscriminator = new Discriminator().propertyName("classType")
                                                        .mapping(classTypeMapping);

        return openApi -> openApi.getComponents().getSchemas().values()
                                .stream()
                                .filter(schema -> "ContainerClass".equals(schema.getName()))
                                .map(schema -> schema.getProperties().get("elements"))
                                .forEach(arraySchema -> ((ArraySchema)arraySchema).getItems().discriminator(classTypeDiscriminator));
    

我在我的合同文件中得到了预期的结果。

【讨论】:

【参考方案2】:

这是默认的生成结构。由 swagger-api 直接处理(而不是 springdoc-openapi。

生成的 OpenAPI 描述看起来很正确。

使用springdoc-openapi,您可以定义一个OpenApiCustomiser Bean,您可以在其中更改在OpenAPI级别上定义的components元素的元素:

https://springdoc.org/faq.html#how-can-i-customise-the-openapi-object-

【讨论】:

感谢您的信息。我要去看看这个链接。当我设法找到解决方案时,我会更新帖子。

以上是关于OpenApi - 有没有办法在使用 springdoc-openapi-maven-plugin 生成的合同中使用带有鉴别器部分的组合模式?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 OpenAPI 3.0 中描述两种不同的响应类型?

如何在 spring-webflux RouterFunction 端点中使用 OpenApi 注释?

使用 springdoc-openapi 和 spring-boot-starter-data-mongodb 生成 OpenAPI 文档

生成 Spring 代码时如何将 OpenAPI“oneOf”属性与 openapi-generator-maven-plugin 一起使用

在 Spring Boot 中使用 Gradle 从 Swagger OpenAPI 生成 RestClient 存根

如何使用 OpenApi 自定义 swagger-ui.html url