【问题标题】:Define array of multiple models in Swagger 2.0在 Swagger 2.0 中定义多个模型的数组
【发布时间】:2016-12-12 07:39:19
【问题描述】:

这是我第一次涉足 Swagger,所以请保持温和。

我有以下定义:

definitions:
  Payload:
    type: object
    properties:
      indicators:
        type: array
        items:
          $ref: '#/definitions/Indicator'
  Indicator:
    type: object
    properties:
      type:
        type: string
      computeOn:
        type: array
        items:
          type: string
        default:
          - close
      parameters:
        type: object
  BBANDS:
    properties:
      type:
        type: string
        default: BBANDS
      computeOn:
        type: array
        items:
          type: string
        default:
          - close
      parameters:
        type: object
        properties:
          timeperiod:
            type: integer
            format: int32
            default: 5
          nbdevup:
            type: integer
            format: int32
            default: 2
          nbdevdn:
            type: integer
            format: int32
            default: 2
          matype:
            type: integer
            format: int32
            default: 0
  DEMA:
    properties:
      type:
        type: string
        default: DEMA
      computeOn:
        type: array
        items:
          type: string
        default:
          - close
      parameters:
        type: object
        properties:
          timeperiod:
            type: integer
            format: int32
            default: 5

所以Payload 有一个名为indicator 的属性,它是Indicators 的数组。 BBANDSDEMAtype Indicator 的模型(我知道这不会转化为 Swagger)。我想做的是用它们的默认值定义一个实际模型的数组,在本例中为BBANDSDEMA。像这样的:

definitions:
  Payload:
    type: object
    properties:
      indicators:
        type: array
        items:
          - '#/definitions/BBANDS'
          - '#/definitions/DEMA'

definitions:
  Payload:
    type: object
    properties:
      indicators:
        type: array
        items:
          - $ref '#/definitions/BBANDS'
          - $ref '#/definitions/DEMA'

当然,两者都不起作用。原因是虽然Indicator 模型正确描述了indicator,但不同的indicators 可以有不同的参数集。

有没有办法从本质上定义几个模型的列表,或者将BBANDSDEMA 模型映射到Indicator

编辑:在 Swagger 编辑器中使用@Helen 的第一个建议的结果

【问题讨论】:

    标签: swagger swagger-2.0


    【解决方案1】:

    Swagger/OpenAPI 2.0 不支持items 的多种类型,但有几种方法可以描述您的需求。

    选项 1 - 模型继承

    只要有一个字段是模型之间共有的,可以用来区分它们,就可以使用模型继承:

    https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaDiscriminator https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#composition-and-inheritance-polymorphism

    在您的示例中,此属性为 typetype="BBANDS"type="DEMA")。所以你可以:

    • 使用allOfIndicator继承BBANDSDEMA模型。
    • discriminator: type添加到Indicator,表示type属性将用于区分子模型。
    • Payload 定义为Indicator 的数组。这样,它实际上可以是BBANDS 的数组或DEMA 的数组。

    definitions:
      Payload:
        type: object
        properties:
          indicators:
            type: array
            items:
              $ref: '#/definitions/Indicator'
    
      Indicator:
        type: object
        properties:
          type:
            type: string
            # Limit the possible values if needed
            #enum:
            #  - BBANDS
            #  - DEMA
          computeOn:
            type: array
            items:
              type: string
            default:
              - close
    
        # The "type" property will be used to distinguish between the sub-models.
        # The value of the "type" property MUST be the schema name, that is, "BBANDS" or "DEMA".
        # (Or in other words, the sub-model schema names must match possible values of "type".)
        discriminator: type
        required:
          - type
    
      BBANDS:
        allOf:
          - $ref: '#/definitions/Indicator'
          - type: object
            properties:
              parameters:
                type: object
                properties:
                  timeperiod:
                    type: integer
                    format: int32
                    default: 5
                  nbdevup:
                    type: integer
                    format: int32
                    default: 2
                  nbdevdn:
                    type: integer
                    format: int32
                    default: 2
                  matype:
                    type: integer
                    format: int32
                    default: 0
      DEMA:
        allOf:
          - $ref: '#/definitions/Indicator'
          - type: object
            properties:
              parameters:
                type: object
                properties:
                  timeperiod:
                    type: integer
                    format: int32
                    default: 5
    

    选项 2 - 单一模型

    如果所有parameters 都是整数,则您可以将Indicator 定义为一个哈希映射parameters 的单个模型。但在这种情况下,您将无法为特定指标类型定义准确的 parameters

    definitions:
      Indicator:
        type: object
        properties:
          type:
            type: string
            enum:
              - BBANDS
              - DEMA
          computeOn:
            type: array
            items:
              type: string
            default:
              - close
          parameters:
            type: object
            properties:
              # This is a common parameter in both BBANDS and DEMA
              timeperiod:
                type: integer
                format: int32
                default: 5
            # This will match additional parameters "nbdevup", "nbdevdn", "matype" in BBANDS
            additionalProperties:
              type: integer
    

    【讨论】:

    • 我认为第一个选项会起作用。我明天去看看然后回来。感谢您的详尽解释。
    • 好的,所以我把它粘贴到了swagger编辑器中,在指标部分有红色文本“对象缺少所需的属性'type'”,type是一个文本字段,参数是空(见屏幕打印)。这与仅定义 Indicator 对象相同。
    • @JasonStrippel:所以您使用该定义作为 POST/PUT/PATCH 请求有效负载。该表单用于向您的 API 主机发送示例请求,因此您需要填写将包含在示例请求中的对象字段。该错误意味着您需要为type 指定一个值,因为type 在您的定义中被标记为必需属性。
    • 因此,当我使用 JavaScript 生成的客户端执行此操作时,json 会返回子模型的不同值,但是当我将返回的数据设置为我的对象时,该对象的唯一值keep 是类型鉴别器。所有附加值都将丢失。你知道有没有办法解决这个问题?否则,我可能只需要使用单个模型。
    • @srchulo 抱歉,我不熟悉 JavaScript 代码生成。我建议您 ask a new question,和/或询问您使用的 codegen 的开发人员(例如,如果您使用 Swagger Codegen,您可以在 Swagger Codegen repository 中询问)。
    【解决方案2】:

    数组类型中的AFAIK可以保存一种类型,如果您想在一个数组下有多种类型,则需要定义另一个超类型并将子类型包装在其中(可能使用对象类型),如下所示。这个限制是因为 swagger-2.0 不支持 json-schema.org 的所有功能,oneOfanyOfallOf 等等都是其中的一部分。

    但是您可以使用 swagger-2.0 提供的第三方扩展选项。您可以使用 x- 命名 Key,这意味着您可以像 x-oneOf 一样包含这些 oneOf,并且在解析架构时,您可以使用 json-schema 解析器和 swagger 架构解析器。

    下面给出一个这样的例子,

    Json 模式

    {
      "id": "http://some.site.somewhere/entry-schema#",
      "$schema": "http://json-schema.org/draft-04/schema#",
      "description": "schema for an fstab entry",
      "type": "object",
      "required": [
        "storage"
      ],
      "properties": {
        "storage": {
          "type": "object",
          "oneOf": [
            {
              "$ref": "#/definitions/diskDevice"
            }
          ]
        },
        "deviceList": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/Device"
          }
        }
      },
      "definitions": {
        "diskDevice": {
          "type": "object",
          "properties": {
            "label": {
              "type": "string"
            }
          },
          "required": [
            "label"
          ]
        },
        "blockDevice": {
          "type": "object",
          "properties": {
            "blockId": {
              "type": "number"
            }
          },
          "required": [
            "blockId"
          ]
        },
        "CharDevice": {
          "type": "object",
          "properties": {
            "charDeviceName": {
              "type": "string"
            }
          },
          "required": [
            "charDeviceName"
          ]
        },
        "Device": {
          "type": "object",
          "oneOf": [
            {
              "$ref": "#/definitions/diskDevice"
            },
            {
              "$ref": "#/definitions/blockDevice"
            },
            {
              "$ref": "#/definitions/CharDevice"
            }
          ]
        }
      }
    }
    

    数据或负载

    {
    "storage": {"label": "adsf"},
    "deviceList": [{"label": "asdf"}, {"blockId": 23}, {"charDeviceName": "asdf"}]
    }
    

    使用此站点来处理您的示例数据 - http://www.jsonschemavalidator.net/

    注意deviceList 属性及其构造方式。希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2016-08-21
      • 1970-01-01
      • 1970-01-01
      • 2020-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-22
      相关资源
      最近更新 更多