我最近在学习 OpenAPI,想了解最佳实践。
假设我有一个名为 Person
的资源, 定义于 components/schemas
如下:
Person:
type: object
required:
- id
- name
- age
properties:
id:
readOnly: true
type: integer
name:
type: string
age:
type: integer
我已经做了
id
只读,因为当我这样做时 post
或 patch
,ID 将作为 URL 的一部分传递。见 https://swagger.io/docs/specification/data-models/data-types/name
和 age
当客户端尝试使用 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
到“新名称”,我正在覆盖它。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"]}
这样我就可以更新
name
至 null
还有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
的所有属性并允许部分更新。这个解决方案仍然感觉很糟糕。此外,它不适用于嵌套对象和可为空属性的部分更新。
(实际上,由于
id
是 readOnly
,您还可以在 required: [id]
上添加 PersonProperties
并从 id
上的 required
列表中删除 Person
)
关于api - 如何正确使用 OpenAPI 使用补丁方法更新资源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62358406/