【问题标题】:Re-using model with different required properties重用具有不同所需属性的模型
【发布时间】:2016-11-28 08:13:12
【问题描述】:

我有一个使用复杂模型的路径,每个 http 方法具有几乎相同的属性。问题是我想为 PUT 和 POST 的请求定义 一些 必需的属性,而 GET 响应中不需要任何属性(因为服务器总是返回所有属性,并且在文档的其他地方提到) .

我创建了一个简单的 cat API 来演示我的尝试。这个想法是,对于 GET 响应,响应模型没有任何标记为 required,但 PUT 的请求必须具有 cat 的名称。

swagger: "2.0"

info:
  title: "Cat API"
  version: 1.0.0

paths:
  /cats/{id}:
    parameters:
      - name: id
        in: path
        required: true
        type: integer
    get:
      responses:
        200:
          description: Return a cat
          schema:
            $ref: "#/definitions/GetCat"
    put:
      parameters:
        - name: cat
          in: body
          required: true
          schema:
            $ref: "#/definitions/PutCat"
      responses:
        204:
          description: Cat edited

definitions:
  Cat:
    type: object
    properties:
      name:
        type: string
  GetCat:
    allOf:
      - $ref: "#/definitions/Cat"
    properties:
      id:
        type: integer
  PutCat:
    type: object
    required:
      - name
    properties:
      $ref: "#/definitions/Cat/properties"

Swagger 编辑器说这是一个有效的规范,但 name 是根据 GET 和 PUT 的要求设置的。 Swagger UI 也是如此。

我还尝试了以下版本的 PutCat:

PutCat:
  type: object
  required:
    - name
  allOf:
    - $ref: "#/definitions/Cat"

但现在一切都是可选的。

我想不通。有没有办法正确地做到这一点?

编辑:

正如Helen 正确提到的那样,我可以使用readOnly 通过GET 和PUT 来解决这个特殊情况。

但是假设我添加了必须为 PUT 提供的 breed 属性(除了 name 属性)。然后我添加 PATCH 方法,可用于更新breedname,而另一个保持不变,我不想根据需要设置任何一个。

【问题讨论】:

    标签: swagger openapi


    【解决方案1】:

    在您的示例中,您可以对 GET 和 POST/PUT 使用单个模型,其属性仅在 GET 响应中使用,标记为 readOnly。来自spec

    readOnly

    将属性声明为“只读”。这意味着它可以作为响应的一部分发送,但不能作为请求的一部分发送。标记为 readOnly 为 true 的属性不应出现在已定义模式的必需列表中。默认值为 false。

    规范看起来像:

        get:
          responses:
            200:
              description: Return a cat
              schema:
                $ref: "#/definitions/Cat"
        put:
          parameters:
            - name: cat
              in: body
              required: true
              schema:
                $ref: "#/definitions/Cat"
          responses:
            204:
              description: Cat edited
    
    definitions:
      Cat:
        properties:
          id:
            type: integer
            readOnly: true
          name:
            type: string
          breed:
            type: string
        required:
          - name
          - breed
    

    这意味着你必须 PUT namebreed:

    {
      "name": "Puss in Boots",
      "breed": "whatever"
    }
    

    GET /cats/{id} 必须返回namebreed,也可以返回id

    {
      "name": "Puss in Boots",
      "breed": "whatever",
      "id": 5
    }
    

    【讨论】:

    • 谢谢,这解决了示例中的问题。但是,我对我的示例有点粗心,并使用为不需要任何内容​​的部分更新添加 PATCH 方法的场景更新了问题。
    • 谢谢,但现在看起来 PATCH 也需要名称和品种(在 Swagger 编辑器中都有星号)。这与原始问题中的问题相同。我相信目前还没有解决方案。
    • @Helen 但是 allOf 关键字也会出现在格式化结构中,很丑。有什么办法可以防止它出现在结构中?
    • $ref 下方的 properties 语法似乎不适用于 Open API 3.0。
    • @ChrisHaines:是的,该示例无效...我将其删除。不幸的是,没有优雅的方法来处理 GET/POST/PATCH 差异。 :(
    【解决方案2】:

    我也遇到过类似的问题。原来我的缩进是错误的。 以下语法应该有效:

    PutCat:
      allOf:
        - $ref: "#/definitions/Cat"
        - type: object
          required: [name]
    

    【讨论】:

    • 这是对put 隐藏某些字段的最佳解决方案,这些字段仅对post 是必需的。通过在“类型”级别添加一个properties:,并且只是带有readOnly: true的属性名称。
    猜你喜欢
    • 1970-01-01
    • 2017-08-22
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    • 1970-01-01
    相关资源
    最近更新 更多