Swagger-Codegen 不使用供应商扩展 x-discriminator-value

Posted

技术标签:

【中文标题】Swagger-Codegen 不使用供应商扩展 x-discriminator-value【英文标题】:Swagger-Codegen does not use vendor extension x-discriminator-value 【发布时间】:2020-05-14 22:38:39 【问题描述】:

我正在尝试使用 swagger-codegen 为模式规范生成 Java API 客户端。 该架构使用供应商扩展 x-discriminator-value 创建继承模型。

例如,我使用了作为 yaml here 找到的模式规范并转换为 json(我用“spec”根包装了结果,因此我可以将结果发送到在线代码生成器,如下所述)。

当我尝试在本地或使用在线代码生成器生成 Java 客户端时,我发现没有使用 x-discriminator-value 值完成去串化。 相反,它是使用模型名称完成的。 我在生成的JSON.java 文件中看到了这一点,其中包含从鉴别器到类的映射:

            classByDiscriminatorValue.put("PhoneSetting".toUpperCase(), PhoneSetting.class);
            classByDiscriminatorValue.put("SceneSetting".toUpperCase(), SceneSetting.class);
            classByDiscriminatorValue.put("TextSetting".toUpperCase(), TextSetting.class);

[要看到这个你可以post上面的json到https://generator.swagger.io/api/gen/clients/java并检查JSON.java文件。

据我了解,我应该知道密钥应该是 x-discriminator-value 值。例如,由于架构具有:

  "SceneSetting": 
      "description": "Scene Setting",
      "x-discriminator-value": "SCENE",
      "allOf": [
        
          "$ref": "#/definitions/SectionSetting"
        , 

那么我应该有一个映射

            classByDiscriminatorValue.put("SCENE".toUpperCase(), SceneSetting.class);

而不是 classByDiscriminatorValue.put("SceneSetting".toUpperCase(), SceneSetting.class);

如果能提供任何帮助,我将不胜感激。

【问题讨论】:

你确定 Swagger Codegen 支持x-discriminator-value?对应的feature request处于打开状态。 @Helen - 谢谢。在这里我看到它被合并了:github.com/swagger-api/swagger-codegen/pull/4252 还有我在docs.apimatic.io/advanced/swagger-codegen-extensions找到的文档 @Helen 如果您认为可以对上述模式示例进行编辑以使生成的 Java 映射具有所需的结果,这也很棒 该 PR 似乎已更新 @JsonSubTypes,它没有触及 JSON.java 文件中的映射。迁移到 OpenAPI 3.0 是否适合您?它内置了对鉴别器映射的支持,因此 codegen 将产生您需要的结果。 @Helen 有可能。我可以引导我到一个可以输入到 codegen 的工作示例,看看它是否生成正确的映射? 【参考方案1】:

在旧版 Swagger 2 上使用供应商扩展 x-discriminator-value 会带来多项限制。

有关更多信息,请参阅 openapi-generator 项目中的 CodegenDiscriminator.java:

// legacyDiscriminatorBehavior == True,这包含: // - 您的 openapi 规范中 discriminMappedModelator 映射条目中模式映射信息的名称 AND // - 子 oneOf + anyOf 模式 + allOf 继承自身模式的后代模式中的 x 鉴别器值映射 AND // - allOf 继承自身架构的后代架构 AND // - 子 oneOf + anyOf 模式

【讨论】:

【参考方案2】:

我建议迁移到 OpenAPI 3.0 - 它内置了对 discriminator mapping 的支持。 OAS2-to-OAS3 converters 可以帮助迁移,但您必须手动更新映射。

在 OpenAPI 3.0 中,鉴别器映射在父架构中指定(而不是在子架构中)。以下示例是 YAML 格式,方便阅读,您可以使用 https://www.json2yaml.com 将其转换为 JSON。

openapi: 3.0.2

components:
  schemas:
    # Parent schema
    SectionSetting:
      type: object
      properties:
        ...
      discriminator:
        propertyName: PROP_NAME
        mapping:
          SCENE: SceneSetting
          ...

    # Child schema
    SceneSetting:
      description: Scene Setting
      allOf:
        - $ref: '#/components/schemas/SectionSetting'
        - ...

确保使用 Swagger Codegen 版本 3.x,因为 2.x 不支持 OpenAPI 3.0。您可以从 Maven Central 获取最新的 3.x CLI JAR:https://mvnrepository.com/artifact/io.swagger.codegen.v3/swagger-codegen-cli

【讨论】:

非常感谢。我能否以这样一种方式定义 in,即父级获取密钥(在我们的示例中为“SCENE”),而不是在架构中显式写入? 你能澄清一下“比如父母拿钥匙的方式”是什么意思吗?对不起,我不太了解。无论如何,默认情况下 - 如果未指定 discriminator.mapping - 映射基于子模式名称,与没有 x-discriminator-value 的 OAS2 中的方式相同。也就是说,假设子架构 SceneSetting 使用带有 "SceneSetting" 值的鉴别器属性 (PROP_NAME)。 discriminator.mapping 部分允许将子架构与鉴别器属性的自定义值(例如 SCENE)相关联。 非常感谢您的详细解释! 非常感谢您的详细解释!在我们的示例中,我的意思是不用写“SCENE”,而是可以指定子模式具有一个包含“场景”键。通过这种方式,我们不需要为每个子模式指定包含映射的映射列表,而映射将始终从子模式属性值(在我们的例子中为 x-discriminator-value 值)到子模式( “场景设置”) 例如,如果我们可以在父模式中声明类似“ChildProprtyNameForMapping: x-discriminator-value”的内容

以上是关于Swagger-Codegen 不使用供应商扩展 x-discriminator-value的主要内容,如果未能解决你的问题,请参考以下文章

Swagger-codegen 开始使用

Swagger-Codegen:如何将所有文件合并到一个文件中以进行客户端代码生成

Swagger-Codegen的简单使用

将生成的 Flask 应用程序代码(Swagger-Codegen)粘合到后端实现的最简洁方法

将 swagger-codegen 项目导入现有的 Android 项目

java:swagger-codegen生成CSharp(C#) Client