OpenAPI 3 -- 属性 在写入时是可选的,但在读取时是必需的
OpenAPI 3 -- Property is optional when written but required when read
我的资源有一个ID(典型案例)。
它还有一个 slug,一个人类可读但仍然唯一的标识符(主要是为了美化 URL)。
创建资源时,此 slug 可选。如果客户提供了一个,它正在被使用;否则,服务器生成一个。
但是在读取资源时slug是必需的。
我们确实希望这种区别很明确,因此任何阅读 OpenAPI 规范的工具都知道会发生什么。
这当然可以使用与 allOf
修饰符链接的不同模式的组合来实现(参见下面的示例),但我想避免必须执行此组合(假设它与第一名)。
所以我的问题是:
在 OpenAPI >= 3.0.2 中有没有办法声明 属性 required-readOnly 和 optional-writeOnly?
使用组合的解决方案:
openapi: 3.0.2
info:
title: Person API
version: 1.0.0
paths:
'/persons/{person-slug}':
get:
parameters:
- $ref: '#/components/parameters/PersonSlug'
responses:
200:
description: Information on a person.
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/SlugRead'
- $ref: '#/components/schemas/Person'
post:
parameters:
- $ref: '#/components/parameters/PersonSlug'
responses:
200:
description: Information on a person.
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/SlugWrite'
- $ref: '#/components/schemas/Person'
components:
parameters:
PersonSlug:
name: 'person-slug'
description: Human readable unique ID of a person.
required: true
in: path
schema:
type: string
schemas:
SlugRead: # required
required:
- slug
properties:
slug:
type: string
readOnly: true
SlugWrite: # not required
properties:
slug:
type: string
Person:
required:
- first_name
- last_name
- birth_date
properties:
first_name:
type: string
last_name:
type: string
birth_date:
type: string
format: date
看不出如何实现完全你所追求的是可能的,但我认为效果可以通过使用单独的字段来定义所需的(只写)与已分配(只读)slug:
Person:
required:
- first_name
- last_name
- birth_date
- assigned_slug
properties:
first_name:
type: string
last_name:
type: string
birth_date:
type: string
format: date
assigned_slug:
type: string
readOnly: true
desired_slug:
type: string
writeOnly: true
虽然不知道是否有任何工具可以用它做正确的事情!
对于将来偶然发现这个问题的人,我使用基本模式和派生模式解决了这个问题。
Person:
properties:
id:
type: integer
readOnly: true
name:
type: string
slug:
type: string
PersonWRITE:
allOf: # name is required, slug is optional and id is not available
- $ref: '#/components/schemas/Person'
- required: [name]
PersonREAD:
allOf: # everything is available and required
- $ref: '#/components/schemas/Person'
- required: [id, name, slug]
它本质上是 OP 的解决方案,但已移至组件级别,因此您不必在 request/response 定义中使用 'allOf'。
编辑:
请注意以下内容将不起作用:
PersonWRITE: #wrong
$ref: '#/components/schemas/Person'
required: [name]
关键是allOf
,它结合了列表中对象的所有属性。在 $ref 扩展后,架构看起来像这样(仍然是一个有效的 yaml,我只是对其进行了一些 jsonified 以指出数组元素实际上是两个属性将被组合的对象):
PersonWRITE:
allOf: [
{
properties: {
id: { type: integer, readOnly: true },
name: { type: string },
slug: { type: string }
}
},
{
required: [name]
}
]
我的资源有一个ID(典型案例)。
它还有一个 slug,一个人类可读但仍然唯一的标识符(主要是为了美化 URL)。
创建资源时,此 slug 可选。如果客户提供了一个,它正在被使用;否则,服务器生成一个。
但是在读取资源时slug是必需的。
我们确实希望这种区别很明确,因此任何阅读 OpenAPI 规范的工具都知道会发生什么。
这当然可以使用与 allOf
修饰符链接的不同模式的组合来实现(参见下面的示例),但我想避免必须执行此组合(假设它与第一名)。
所以我的问题是:
在 OpenAPI >= 3.0.2 中有没有办法声明 属性 required-readOnly 和 optional-writeOnly?
使用组合的解决方案:
openapi: 3.0.2
info:
title: Person API
version: 1.0.0
paths:
'/persons/{person-slug}':
get:
parameters:
- $ref: '#/components/parameters/PersonSlug'
responses:
200:
description: Information on a person.
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/SlugRead'
- $ref: '#/components/schemas/Person'
post:
parameters:
- $ref: '#/components/parameters/PersonSlug'
responses:
200:
description: Information on a person.
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/SlugWrite'
- $ref: '#/components/schemas/Person'
components:
parameters:
PersonSlug:
name: 'person-slug'
description: Human readable unique ID of a person.
required: true
in: path
schema:
type: string
schemas:
SlugRead: # required
required:
- slug
properties:
slug:
type: string
readOnly: true
SlugWrite: # not required
properties:
slug:
type: string
Person:
required:
- first_name
- last_name
- birth_date
properties:
first_name:
type: string
last_name:
type: string
birth_date:
type: string
format: date
看不出如何实现完全你所追求的是可能的,但我认为效果可以通过使用单独的字段来定义所需的(只写)与已分配(只读)slug:
Person:
required:
- first_name
- last_name
- birth_date
- assigned_slug
properties:
first_name:
type: string
last_name:
type: string
birth_date:
type: string
format: date
assigned_slug:
type: string
readOnly: true
desired_slug:
type: string
writeOnly: true
虽然不知道是否有任何工具可以用它做正确的事情!
对于将来偶然发现这个问题的人,我使用基本模式和派生模式解决了这个问题。
Person:
properties:
id:
type: integer
readOnly: true
name:
type: string
slug:
type: string
PersonWRITE:
allOf: # name is required, slug is optional and id is not available
- $ref: '#/components/schemas/Person'
- required: [name]
PersonREAD:
allOf: # everything is available and required
- $ref: '#/components/schemas/Person'
- required: [id, name, slug]
它本质上是 OP 的解决方案,但已移至组件级别,因此您不必在 request/response 定义中使用 'allOf'。
编辑: 请注意以下内容将不起作用:
PersonWRITE: #wrong
$ref: '#/components/schemas/Person'
required: [name]
关键是allOf
,它结合了列表中对象的所有属性。在 $ref 扩展后,架构看起来像这样(仍然是一个有效的 yaml,我只是对其进行了一些 jsonified 以指出数组元素实际上是两个属性将被组合的对象):
PersonWRITE:
allOf: [
{
properties: {
id: { type: integer, readOnly: true },
name: { type: string },
slug: { type: string }
}
},
{
required: [name]
}
]