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

Posted

技术标签:

【中文标题】生成 Spring 代码时如何将 OpenAPI“oneOf”属性与 openapi-generator-maven-plugin 一起使用【英文标题】:How to use OpenAPI "oneOf" property with openapi-generator-maven-plugin when generating Spring code 【发布时间】:2020-10-26 19:40:03 【问题描述】:

我正在开发一个带有 Angular 前端和 RESTful Spring Boot 后端的应用程序

我从 org.openapitools 找到了这个非常方便的 maven 插件 openapi-generator-maven-plugin。凭借其代码生成功能,它有助于在我们的 API 的前端和后端之间实施“合同优先”的方法。但是我们的 swagger 文件在 requestBody 和 responseBody 定义中使用了“oneOf”属性。我试图从中生成 Spring 代码,但生成的 Java 类缺少导入:

import com.pack.api.dto.OneOfLatteCoffeAmericanoCoffe;
import com.pack.api.dto.UNKNOWN_BASE_TYPE;

是否可以将插件与 Swagger 的 oneOf 属性一起使用?我正在使用 Spring Boot 2.3.1、Swagger 3.0 和 Openapi-generator-maven-plugin 4.3

【问题讨论】:

【参考方案1】:

目前,openapi-generator 不支持oneOf。这是 OpenAPI v3 新引入的功能(仅供参考,只有 v2 及以下版本称为“Swagger”,然后已重命名为 OpenAPI)。有各种生成器(Java、Spring、许多其他语言)。我在今年看到contributions have been made 到enable oneOf support。

总而言之,在您可以使用 Spring 生成器利用 OpenAPI v3 规范的这一特性之前,您似乎需要再等一会儿。

编辑:它也列出了on the "short term roadmap":

OAS3.0 功能支持:anyOf、oneOf、回调等

【讨论】:

我一直在努力为大量使用 anyOf 和 oneOf 的 API 生成 php 客户端。经过一些谷歌搜索并发现围绕这个主题的堆栈溢出问题令人惊讶地很少,我猜对多态性的支持真的是代码生成的一个强大的 WIP 主题? 刚刚也遇到了这个问题:(【参考方案2】:

如果您可以修改您的招摇,您可以将oneOf 替换为对抽象类型的引用。

例如,如果你的招摇看起来像这样:

components:
  schemas:
    'Parent':
      'vehicle':
        oneOf:
        - type: object
          properties:
            'car_property':
              type: string
        - type: object
          properties:
            'truck_property':
              type: string

你可以这样修改:

components:
  schemas:
    'Parent':
      type: object
      properties:
        'vehicle':
          $ref: '#/components/schemas/Vehicle'
    #---------------------------------------------------------------------------
    # Abstract class with discriminator 'vehicle_type'
    #---------------------------------------------------------------------------
    'Vehicle':
      type: object
      properties:
        'vehicle_type':
          type: string
          enum: [ 'CAR', 'TRUCK' ]
      discriminator:
        propertyName: vehicle_type
        mapping:
          'CAR': '#/components/schemas/Car'
          'TRUCK': '#/components/schemas/Truck'
    #---------------------------------------------------------------------------
    # Concrete classes
    #---------------------------------------------------------------------------
    'Car':
      allOf:
      - $ref: "#/components/schemas/Vehicle"
      - type: object
        properties:
          'car_property':
            type: string
    'Truck':
      allOf:
      - $ref: "#/components/schemas/Vehicle"
      - type: object
        properties:
          'truck_property':
            type: string

这种大摇大摆的修改使生成器工作。它处理相同的 JSON 对象,尽管我不能 100% 确定它在 OpenAPI 规范中的语义等价。

【讨论】:

在尝试此解决方案时,我仍然在抽象模型中得到:@JsonSubTypes( @JsonSubTypes.Type(value = ERRORUNKNOWN.class, name = "Obj1"), @JsonSubTypes.Type(value = ERRORUNKNOWN.class, name = "Obj2"), ),编译失败。【参考方案3】:

我们为java (jersey2)、csharp-netcore 等一些生成器添加了更好的 oneOf 和 anyOf 支持。请用最新的大师试一试。 SNAPSHOT 版本可以在项目的 README 中找到:https://github.com/OpenAPITools/openapi-generator/

【讨论】:

maven available 5.1.1 不支持 oneof 和 anyof 代码生成。 5.2.0-SNAPSHOT 和 6.0.0-SNAPSHOT 在 maven 上不可用。如果这两个版本支持其中一个,你建议如何尝试?必须在生产代码中使用此实用程序。【参考方案4】:

对我来说,创建的 csharp 生成的模型对象不正确。 它会生成以下内容,

[DataMember(Name = "category", IsRequired = true, EmitDefaultValue = true)]
public OneOfobjectobjectobject Category  get; set; 

它创建一个以单词 Oneof 开头的对象并附加三个对象,因为我的 openapi 规范文档中有三个 oneOfs 用于类别。 有没有办法返回字典或其他东西?上面的代码无法编译。 我的类别的 openapi 架构如下

category:
          title: Category
          oneOf:
            - title: Year
              type: object
              properties:
                type:
                  title: Type
                  enum:
                    - year
                  type: string
              additionalProperties: false
              required:
                - type
            - title: Term
              type: object
              properties:
                type:
                  title: Type
                  enum:
                    - term
                  type: string
                parent:
                  title: Parent
                  oneOf:
                    - title: Academic Period
                      type: object
                      properties:
                        academicPeriod:
                          title: Academic Period
                          type: object
                          properties:
                            id:
                              title: ID
                              description: The global identifier for the Academic Period.
                              type: string
                              format: guid
                              pattern: ^[a-f0-9]8(?:-[a-f0-9]4)3-[a-f0-9]12$
                          additionalProperties: false
                          required:
                            - id
                      additionalProperties: false
                      required:
                        - academicPeriod
                    - title: Academic Year
                      type: object
                      properties:
                        academicYear:
                          title: Academic Year
                          type: number
                      additionalProperties: false
                      required:
                        - academicYear
                preceding:
                  title: Preceding
                  oneOf:
                    - type: object
                      properties:
                        id:
                          title: ID
                          description: The global identifier for the Preceding.
                          type: string
                          format: guid
                          pattern: ^[a-f0-9]8(?:-[a-f0-9]4)3-[a-f0-9]12$
                      additionalProperties: false
                      required:
                        - id
                    - type: object
                      maxProperties: 0
              additionalProperties: false
              required:
                - type
            - title: Subterm
              type: object
              properties:
                type:
                  title: Type
                  enum:
                    - subterm
                  type: string
                parent:
                  title: Parent
                  type: object
                  properties:
                    id:
                      title: ID
                      description: The global identifier for the Parent.
                      type: string
                      format: guid
                      pattern: ^[a-f0-9]8(?:-[a-f0-9]4)3-[a-f0-9]12$
                  additionalProperties: false
                  required:
                    - id
                preceding:
                  title: Preceding
                  oneOf:
                    - type: object
                      properties:
                        id:
                          title: ID
                          description: The global identifier for the Preceding.
                          type: string
                          format: guid
                          pattern: ^[a-f0-9]8(?:-[a-f0-9]4)3-[a-f0-9]12$
                      additionalProperties: false
                      required:
                        - id
                    - type: object
                      maxProperties: 0
                sectionDateOverride:
                  title: Section Date Override
                  oneOf:
                    - type: string
                      enum:
                        - notAllowed
                    - type: string
                      maxLength: 0
              additionalProperties: false
              required:
                - type
                - parent

【讨论】:

以上是关于生成 Spring 代码时如何将 OpenAPI“oneOf”属性与 openapi-generator-maven-plugin 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Boot 中自动生成 API 文档 [关闭]

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

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

如何从 openapi 生成器编译一个在生成的源文件夹中实现接口的项目?

Swagger Gradle 插件在构建期间没有为 spring mvc 正确生成 openapi.json 文件

如何从 OpenAPI 3.0 生成 PDF 或标记?