Dri*_*leX 8 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
Run Code Online (Sandbox Code Playgroud)
我已将idreadOnly设为只读,因为当我执行postor 时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}
Run Code Online (Sandbox Code Playgroud)
但是,由于我已name按要求进行了定义,因此我无法做到。我可以想到几种解决方案,但它们都有缺陷:
required限制。但如果我这样做,我将失去对post和的验证get。patch,例如PersonUpdate,使用required删除。显然,这会导致冗余。patch,我确实传递了所有字段,但是对于那些我不想更新的字段,我传递了一个无效值,例如PATCH /Person/1
{"age": 40, "name": null}
Run Code Online (Sandbox Code Playgroud)
并制作所有字段nullable,并让服务器忽略这些值。但是如果我想null在 DB 中设置 name呢?
PUT用于更新,并始终传递所有必填字段。但是如果我的数据已经过时怎么办?例如当我做PUT /Person/1
{"age": 40, "name": "Old Name"}
Run Code Online (Sandbox Code Playgroud)
其他一些客户端已经更改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
Run Code Online (Sandbox Code Playgroud)
然后我可以这样做
PATCH /Person/1
{"age": 40, "name": null, _fields: ["age"]}
Run Code Online (Sandbox Code Playgroud)
这样一来,我可以更新name到null以及
PATCH /Person/1
{"age": 40, "name": null, _fields: ["age", "name"]}
Run Code Online (Sandbox Code Playgroud)
这种方法似乎可行,但有没有更好或被广泛接受的做法?
mul*_*008 13
我想出了以下解决方案:
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
Run Code Online (Sandbox Code Playgroud)
PersonProperties充当构成人员模型的简单属性集合。它没有指定任何required字段。
Person重用 的所有属性PersonProperties,此外还指定需要哪些属性。PersonUpdate重用 的所有属性PersonProperties并允许部分更新。
这个解决方案仍然感觉很hacky。此外,它不适用于嵌套对象和可为空属性的部分更新。
(事实上,由于idis readOnly,您还可以required: [id]在 上添加和从列表中PersonProperties删除)idrequiredPerson
通过将模式拆分为多个可组合的模式,我们可以将模式分层,而无需重复。我们甚至可以通过将可选属性设置为空来支持通过 PATCH 删除属性。
示例 OpenAPI 定义允许通过 PATCH 端点进行部分更新(已验证):
openapi: 3.0.0
info:
title: Sample API with reusable schemas and partial updates (PATCH)
version: 1.0.0
paths:
/customers:
post:
tags:
- Customer
requestBody:
$ref: '#/components/requestBodies/CreateCustomer'
responses:
201:
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerId'
get:
tags:
- Customer
responses:
200:
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Customer'
/customers/{CustomerId}:
get:
tags:
- Customer
parameters:
- $ref: '#/components/parameters/CustomerId'
responses:
200:
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
put:
tags:
- Customer
requestBody:
$ref: '#/components/requestBodies/CreateCustomer'
parameters:
- $ref: '#/components/parameters/CustomerId'
responses:
204:
description: Updated
patch:
tags:
- Customer
requestBody:
description: Update customer with properties to be changed
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/CustomerProperties'
- type: object
properties:
Segment:
nullable: true
parameters:
- $ref: '#/components/parameters/CustomerId'
responses:
204:
description: Updated
components:
schemas:
CustomerProperties:
type: object
properties:
FirstName:
type: string
LastName:
type: string
DOB:
type: string
format: date-time
Segment:
type: string
enum:
- Young
- MiddleAged
- Old
- Moribund
CustomerRequiredProperties:
type: object
required:
- FirstName
- LastName
- DOB
Id:
type: integer
CustomerId:
type: object
properties:
Id:
$ref: '#/components/schemas/Id'
Customer:
allOf:
- $ref: '#/components/schemas/CustomerId'
- $ref: '#/components/schemas/CustomerProperties'
- $ref: '#/components/schemas/CustomerRequiredProperties'
parameters:
CustomerId:
name: CustomerId
in: path
required: true
schema:
$ref: '#/components/schemas/Id'
requestBodies:
CreateCustomer:
description: Create a new customer
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/CustomerProperties'
- $ref: '#/components/schemas/CustomerRequiredProperties'
Run Code Online (Sandbox Code Playgroud)
改编自: https: //stoplight.io/blog/reuse-openapi-descriptions/
| 归档时间: |
|
| 查看次数: |
1627 次 |
| 最近记录: |