api - 如何正确使用 OpenAPI 使用补丁方法更新资源?

标签 api rest swagger openapi

我最近在学习 OpenAPI,想了解最佳实践。
假设我有一个名为 Person 的资源, 定义于 components/schemas如下:

Person:
  type: object
  required:
    - id
    - name
    - age
  properties:
    id:
      readOnly: true
      type: integer
    name:
      type: string
    age:
      type: integer

我已经做了 id只读,因为当我这样做时 postpatch ,ID 将作为 URL 的一部分传递。见 https://swagger.io/docs/specification/data-models/data-types/
nameage当客户端尝试使用 post 创建新人时必须出现方法,或 get一个人,因此他们被定义为 required .

我的问题是关于 patch : 如果我只想更新一个人的age怎么办或 name独立?理想情况下,我想做类似的事情
PATCH /person/1

{"age": 40}

但是,由于我已经定义了 name按照要求,我做不到。我可以想到几种解决方案,但它们都有缺陷:
  • 删除 required限制。但是如果我这样做,我将失去对 post 的验证。和 get .
  • patch 使用单独的架构,例如PersonUpdate , 与 required移除。显然,这会导致冗余。
  • 当我这样做时 patch ,我确实传递了所有字段,但对于那些我不想更新的字段,我传递了一个无效值,例如
  • PATCH /Person/1
    
    {"age": 40, "name": null}
    

    并制作所有字段nullable ,并让服务器忽略这些值。但是如果我确实想将 name 设置为 null 怎么办?在数据库?
  • 我用 PUT用于更新,并始终传递所有必填字段。但是如果我的数据已经过时怎么办?例如。当我这样做时
  • PUT /Person/1
    
    {"age": 40, "name": "Old Name"}
    

    其他一些客户端已经更改 name到“新名称”,我正在覆盖它。
  • 像方法 3,但我在做 patch 时传递了额外的字段指示服务器应该关心的字段,是否使用查询参数,如 ?fields=age ,或将其添加到 JSON 正文中。所以我可以更改 requestBody类似于
  •       requestBody:
            content:
              application/json:
                schema:
                  allOf:
                    - $ref: '#/components/schemas/Person'
                    - type: object
                      properties:
                        _fields:
                          type: array
                          items:
                            type: string
    

    然后我可以这样做
    PATCH /Person/1
    
    {"age": 40, "name": null, _fields: ["age"]}
    

    这样我就可以更新namenull还有
    PATCH /Person/1
    
    {"age": 40, "name": null, _fields: ["age", "name"]}
    

    这种方法似乎可行,但有没有更好或被广泛接受的做法?

    最佳答案

    我想出了以下解决方案:

    Person:
      type: object
      allOf:
        - $ref: '#/components/schemas/PersonProperties'
        - required:
          - id
          - name
          - age
    UpdatePerson:
      type: object
      allOf:
        - $ref: '#/components/schemas/PersonProperties'
    PersonProperties:
      type: object
      properties:
        id:
          readOnly: true
          type: integer
        name:
          type: string
        age:
          type: integer
    
    PersonProperties充当构成人员模型的简单属性集合。它没有指定任何 required领域。Person重用 PersonProperties 的所有属性并且,另外指定需要哪一个。 PersonUpdate重用 PersonProperties 的所有属性并允许部分更新。
    这个解决方案仍然感觉很糟糕。此外,它不适用于嵌套对象和可为空属性的部分更新。
    (实际上,由于 idreadOnly ,您还可以在 required: [id] 上添加 PersonProperties 并从 id 上的 required 列表中删除 Person )

    关于api - 如何正确使用 OpenAPI 使用补丁方法更新资源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62358406/

    相关文章:

    javascript - 在 AngularJS 中保存创建的数据

    javascript - 如何使用 Api 将正在播放的 last.fm 添加到我的网站中

    java - key 未加载: Key<Frame> while POSTing source frame through ParseSetup in H2O API call

    rest - 将验证码 token 放在 REST API 中的最佳位置在哪里

    rest - Django REST Framework 与accepted_renderer 错误

    javascript - 用于在桌面应用程序中操作 html/Javascript DOM 元素的 Java API?

    rest - Protractor/Jasmine 在测试失败时发送 REST 调用

    asp.net-core - Swashbuckle.AspNetCore 所需的查询字符串参数

    c# - swagger、.net core api 中的响应内容类型

    swagger - 如何在 Swagger UI 中使用 OpenAPI 3.0 响应 "links"?