Swagger:取决于字段值的变体模式形状

时间:2017-10-04 04:35:59

标签: swagger swagger-2.0

我的模型定义为:

Event:
  type: object
  properties:
    id:
      type: string
    timestamp:
      type: string
      format: date-time
    type:
      type: string
      enum:
        - click
        - open
        - sent
    click:
      type: object
      properties:
        url:
          type: string
        title:
          type: string
    open:
      type: object
      properties:
        subject:
          type: string
    sent:
      type: object
      properties:
        subject:
          type: string
        from:
          type: string
        to:
          type: string

但是,根据type枚举字段的值,形状实际上是不同的。它可以是三个中的一个,我试图在examples(见下文)中定义差异,但这不起作用。

如您所见,下面显示了三个示例,每个示例都有所不同,具体取决于type。这就是API的行为方式,但记录这种预期的行为并不简单。

  examples:
    application/json:
      - id: >
          ad1b12f0-63a8-47b5-9820-3e447143ce7e
        timestamp: >
          2017-09-29T16:45:20.000+00:00
        type: click
        click:
          url: >
            www.some-website-somewhere.org/12345
          title: >
            Click here!
      - id: >
          d9e787fa-db49-4bd8-97c3-df45f159295c
        timestamp: >
          2017-09-29T16:45:20.000+00:00
        type: open
        open:
          subject: >
            Have you seen this?
      - id: >
          30adc194-0f5f-4889-abd4-4fa964d0bb42
        timestamp: >
          2017-09-29T16:45:20.000+00:00
        type: sent
        sent:
          subject: >
            Have you seen this?
          from: >
            bill@office.gov
          to: >
            mon@gmail.com

我读了几个提到这个不可能的地方,但我希望得到一些“开箱即用”的思想家来帮助我找到解决方案。

1 个答案:

答案 0 :(得分:1)

可以使用model inheritance/compositiondiscriminator

首先,定义仅包含公共属性的基本模型Event,并将type属性标记为discriminator

definitions:
  Event:
    type: object
    discriminator: type
    required:
      - type  # discriminator property is required
    properties:
      id:
        type: string
        example: ad1b12f0-63a8-47b5-9820-3e447143ce7e
      timestamp:
        type: string
        format: date-time
        example: 2017-09-29T16:45:20.000+00:00
      type:
        type: string
        enum:
          - click
          - open
          - sent

然后通过Event从基础allOf模型继承点击/打开/发送的模型。子模型的名称必须与discriminator属性的值相同。在您的示例中,模型必须命名为clickopensent。如果您使用Swagger UI,则可以添加title以覆盖显示的模型名称。

  click:
    title: ClickEvent
    allOf:
      - $ref: '#/definitions/Event'
      - type: object
        properties:
          click:
            type: object
            properties:
              url:
                type: string
                example: www.some-website-somewhere.org/12345
              title:
                type: string
                example: Click here!

在操作中,使用基本模型(Event)作为请求或响应模式:

responses:
  200:
    description: OK
    schema:
      $ref: '#/definitions/Event'

客户端应检查discriminator属性的值(在此示例中为type)以确定要使用的继承模型。

注意Swagger UI用户: Swagger UI和Swagger Editor目前不支持基于discriminator的切换模型。关注this issue以获取更新。


OpenAPI 3.0 中,它更容易 - 您只需使用oneOf为请求或响应定义备用架构。

responses:
  '200':
    description: OK
    content:
      application/json:
        schema:
          oneOf:
            - $ref: '#/components/schemas/ClickEvent'
            - $ref: '#/components/schemas/OpenEvent'
            - $ref: '#/components/schemas/SentEvent'
          # Optional mapping of `type` values to models
          discriminator:
            propertyName: type
            mapping:
              click: '#/components/schemas/ClickEvent'
              open:  '#/components/schemas/OpenEvent'
              sent:  '#/components/schemas/SentEvent'