【问题标题】:Generating from openapi to golang using openapi-generator-cli containing oneOf results in broken code使用包含 oneOf 的 openapi-generator-cli 从 openapi 生成到 golang 会导致代码损坏
【发布时间】:2020-12-03 10:58:38
【问题描述】:

在包含 oneOf 关键字的 openapi 3.3 规范上使用 openapi-generator-cli 生成 golang 代码导致损坏且无法编译的代码。 Openapi-generator-cli docker-hub: Digest:sha256:829f0b601005c28950ed55c65d853f2caead265730782b2c7c48812bf8135222

鉴于此架构:

"schemas": {
  "Foo": {
    "type": "object",
    "properties": {
      "Bar": {
        "oneOf": [
          {"$ref": "#/components/schemas/FooBar"},
          {"$ref": "#/components/schemas/BarFoo"}
        ]
      }
    }
  },
  "FooBar": {
    "type": "object",
    "title": "FooBar",
    "properties": {
      "example": {
        "type": "string"
      }
    }
  },
  "BarFoo": {
    "type": "object",
    "title": "BarFoo",
    "properties": {
      "example": {
        "type": "string"
      }
    }
  }
}

结果是:

type Foo struct {
    Bar *OneOfFooBarBarFoo `json:"Bar,omitempty"`
}

我已经读到对此的支持是有限的,应该会产生 interface{},我会对这样的结果感到满意。 我运行的命令是:

openapi-generator-cli generate \
        -i "/swagger.json" \
        -g go \
        --global-property models,supportingFiles=utils.go,modelDocs=false \
        --additional-properties  \
        --minimal-update \
        -p enumClassPrefix=true \
        --enable-post-process-file \
        --additional-properties packageName="Some Name" \
        -o "/Some_Location"

有人知道这个问题的解决方案吗?我试图找到答案,但大多数已知问题似乎已经敲定

【问题讨论】:

    标签: go openapi openapi-generator


    【解决方案1】:

    定义的 openAPI 文件有些含糊不清。因此,即使绑定可以编译,它们也无法正常工作。 FooBar 和 BarFoo 模式需要不同,以允许接收端实例化正确的对象。

    产生相对简单的代码和工作的一个想法是有一个携带对象类型的字段。这称为discriminator

    下面是它如何适合您的代码:

    schemas:
      Foo:
        type: object
        properties:
          Bar:
            $ref: "#/components/schemas/FooOrBar"
      FooOrBar:
        oneOf:
          - "$ref": "#/components/schemas/FooBar"
          - "$ref": "#/components/schemas/BarFoo"
        discriminator:
          propertyName: className
          mapping:
            FooBar: '#/components/schemas/FooBar'
            BarFoo: '#/components/schemas/BarFoo'
      FooBar:
        type: object
        title: FooBar
        required: [className]
        properties:
          example:
            type: string
          className:
            type: string
      BarFoo:
        type: object
        title: BarFoo
        required: [className]
        properties:
          example:
            type: string
          className:
            type: string
    

    请注意,我添加了一个新的命名类来保存oneOf,以便生成一个命名容器。这避免了您观察到的问题。

    为了进一步使其成为一个工作示例,我正在添加鉴别器。

    我最后在两个模式中添加了必需的鉴别器属性。您可以定义一个“基本”模式并将其包含在allOf 中。后者将生成更清晰、更易于维护的代码。

    原则上,您可以放弃“鉴别器”,而是在需要选择的每个架构中定义具有单个值的必需枚举字段。我怀疑,这将导致代码效率降低,因为需要完整的模式验证来选择正确的类型。使用判别器方法只需评估一个字段。

    原则上,如果您的所有模式在结构上都非常不同,并且无法验证代替另一个鉴别器或枚举是不必要的。在 JSON 世界中,断言“一个不能代替另一个验证”是一个非常模糊的定义。我认为在 JSON 模式中使用它是一个彻头彻尾的错误,因为升级到你的模式可能会受到威胁。

    我用下面这行来发出 go 代码

    java -jar openapi-generator-cli.jar generate 
      -g go
      -i FooBar.yaml
      -o foo_go
      --additional-properties=useOneOfDiscriminatorLookup=true
      --additional-properties=disallowAdditionalPropertiesIfNotPresent=false
    

    注意--additional-properties=useOneOfDiscriminatorLookup=true。这样就可以发出鉴别器的逻辑。

    另一个指令将绑定切换到 JSON 模式兼容模式,即保留与模式不匹配的元素。这是一个很长的讨论为什么你想要这个。现在假设 JSON 模式有这个假设是有原因的。

    请注意,Java 可以使用相同的协议,即实际的 JSON 文件,但在 Java 中,您需要使用“allOf”结构。

    【讨论】:

      猜你喜欢
      • 2020-10-26
      • 2022-10-13
      • 2022-07-23
      • 2021-11-15
      • 1970-01-01
      • 1970-01-01
      • 2019-12-07
      • 1970-01-01
      • 2021-08-08
      相关资源
      最近更新 更多