Copyright © 2025 the Linux Foundation
本文件中的 “MUST”(必须)、 “MUST NOT”(不能)、 “REQUIRED”(要求)、 “SHALL”(应)、 “SHALL NOT”(不应)、 “SHOULD”(推荐)、 “SHOULD NOT”(不推荐)、 “RECOMMENDED”(建议)、 “NOT RECOMMENDED”(不建议)、 “MAY”(可以)和 “OPTIONAL”(可选)等关键词的解释,如 BCP 14 [RFC2119] [RFC8174] 所述,仅在这些词全部大写时适用。
本文件采用 Apache License, Version 2.0 许可协议。
OpenAPI 规范(OAS)定义了一个语言无关的标准 HTTP API 接口,允许人类和计算机无需访问源代码、文档或通过网络流量检查,就能发现并理解服务的能力。经过规范定义后,使用者可通过解析与序列化 HTTP 消息到 数据模型,以最少的实现逻辑与远程服务交互。
一个 OpenAPI 描述 (OAD) 可以被文档生成工具用于展示 API,代码生成工具用于各类编程语言的服务端和客户端生成,以及测试工具和众多其他场景。
有关 OpenAPI 的使用示例和更多文档,请访问 [OpenAPI-Learn]。
关于扩展注册表和 OpenAPI Initiative 发布的其他规范,以及本规范的权威渲染,请访问 spec.openapis.org。
OpenAPI 规范采用 major.minor.patch
的版本管理方式。major.minor 部分(如 3.1)SHALL 指定
OAS 功能集;.patch 版本则是修正文档或提供说明,不增加功能集。支持 OAS 3.1 的工具 SHOULD
兼容所有 OAS 3.1.* 版本。工具 SHOULD NOT 区分 patch 版本,例如不区分 3.1.0 和
3.1.1。
部分字段或功能可能被标记为 弃用(Deprecated)。 这些字段和功能仍属于规范,可以正常使用。 但 OpenAPI 描述作者建议尽量用新字段或新功能替换弃用项。
目前,弃用元素预计会保留到 OAS 下一个主版本。但未来的小版本可能会规定弃用元素后续移除的策略。
偶尔,OAS 的 minor 版本会因带来显著好处而做出部分非兼容性变更,前提是影响较小。
本规范认为某些情景属于未定义或实现自定义行为。
所谓未定义行为,至少部分情况下可能导致与规范相悖的结果。这种定义多用于无法或不便检测矛盾的场景。各实现 MAY 为兼容历史或规范旧版本的模糊文本而支持未定义场景。这在不少情况下能产生正确结果,但 NOT RECOMMENDED 依赖于此,因为无法保证对所有工具乃至未来规范版本都有效,哪怕这些版本在其它方面与当前版本严格兼容。
而实现自定义行为,是指规范对某要求允许多种符合规范但实现方式不同的策略。这样描述用于指代模糊要求,API 描述作者RECOMMENDED 应避免,以提升工具兼容性。与未定义行为不同,若能确保所有相关工具实现一致,则依赖实现自定义行为是安全的。
符合 OpenAPI 规范的 OpenAPI 文档本身是一个 JSON 对象,可用 JSON 或 YAML 格式表示。本规范中的示例为简洁起见采用 YAML 展示。
规范中的所有字段名称均为区分大小写。作为 map 键使用的字段也包括在内,除非明确说明为不区分大小写。
OAS 对象包含两类字段:声明名称的固定字段,以及声明名称模式的模式字段。
模式字段在其所处对象中 MUST 唯一。
注意:虽然 API 可用 YAML 或 JSON 格式描述,但 API 请求和响应体以及其它内容没有强制为 JSON 或 YAML。
为保持 YAML 与 JSON 的格式互转能力,YAML 1.2 版 RECOMMENDED 使用,同时遵循 [RFC9512] 第 3.4 节的补充约束。
规范旧版本建议将 YAML 限制为其“JSON”schema 规则集,但不少这种(名字虽是 JSON,但实际上不能被 JSON 表示的)值。OAD 作者 SHOULD NOT 依赖这类不兼容 JSON 的 YAML 值。
因 OpenAPI 规范中的大多数字段名和字段值都区分大小写,本文档会特别标注不敏感场景。但只要字段名或字段值与 HTTP 概念直接对应,其大小写敏感规则即遵循 HTTP,无论本文档是否特别说明。
规范各处的 description 字段均支持 [CommonMark] markdown 格式。OpenAPI
工具渲染富文本时 MUST 至少支持 [CommonMark-0.27]
所述的 markdown 语法。工具 MAY 可忽略部分 CommonMark 或扩展特性以确保安全。
CommonMark 0.27 仅作为最低要求,允许工具在此基础上实现扩展,但这些扩展均属于实现自定义行为,无法保证互操作。OpenAPI 描述作者 SHOULD 考虑使用这些扩展时,在只支持最低要求的工具下的展示效果。
本节描述了 OpenAPI 描述格式的结构。 此处内容是格式的唯一规范性描述。 spec.openapis.org 提供了 JSON Schema,仅供参考。 如果 JSON Schema 与本节内容有不同,则本节 MUST 被视为权威。
在以下描述中,如果某字段未被明确声明为 REQUIRED 或未使用 MUST 或 SHALL 描述,则可视为 OPTIONAL 可选项。
这是OpenAPI 描述的根对象。
除了必需字段外,components、paths 或 webhooks 字段至少有一个 MUST 存在。
| 字段名 | 类型 | 说明 |
|---|---|---|
| openapi | string |
REQUIRED. 字符串 MUST 是
OpenAPI 规范的版本号。工具 SHOULD 通过 openapi 字段解释 OpenAPI 文档。此字段与 info.version(描述文档版本)无关。 |
| $self | string |
该字符串 MUST 符合 [RFC3986] 第 4.1 节 的 URI 引用格式。
$self 字段为本文件的自我指定 URI,也作为其基础 URI,参见 [RFC3986] 第 5.1.1 节。工具 MUST 在此字段存在时,用其定义的 URI 标识API 描述 URI 的目标。可参考 基础 URI 建立 了解缺失或相对情况下的行为,参考 附录
F 了解使用 $self 进行引用解析的示例。
|
| info | Info 对象 | REQUIRED。提供关于 API 的元数据。元数据 MAY 可被工具使用。 |
| jsonSchemaDialect | string |
作为本 OAS 文档中 Schema 对象 内 $schema 关键字的默认值。MUST 是 URI 格式。 |
| servers | [Server 对象] | Server 对象数组,提供目标服务器的连接信息。如果未提供 servers 字段或为空数组,则默认值为包含一个 Server 对象 且其 url 为
/ 的数组。
|
| paths | Paths 对象 | API 的可用路径和操作。 |
| webhooks | Map[string, Path Item
对象] |
可被接收为此 API 的部分的入站 webhook,API 使用者 MAY 可选择实现。与
callbacks 功能密切相关,本节描述 API 调用之外的请求,如带外注册。键为唯一字符串,引用每个 webhook,可选引用 Path Item
对象,其描述 API 提供者可发起的请求及期望响应。可参考 示例。
|
| components | Components 对象 | 用于存放 OpenAPI 描述中的各种对象的元素。 |
| security | [Security Requirement 对象] | 声明 API 可用的安全机制。值列表包含可选用的不同 Security Requirement
对象,只需满足其中一个即可授权请求。单独操作可覆盖该定义。列表可不完整,甚至可为空或缺失。若需显式可选安全,可在数组中添加空安全需求 {}。 |
| tags | [Tag 对象] | OpenAPI 描述中用到的标签列表含附加元数据。标签顺序可用于反映解析工具中的顺序。并非 Operation 对象 用到的所有标签都需声明。未声明的标签 MAY 可随机或按工具逻辑组织。列表中的每个标签名称 MUST 唯一。 |
| externalDocs | External Documentation 对象 | 附加的外部文档。 |
该对象 MAY 可通过 规范扩展 扩展。
为确保互操作性,如有 $self 字段,引用 MUST 使用目标文档的 $self URI。
工具实现 MAY 支持用其他 URI(如获取 URI)作为引用目标,即使 $self 已存在,但该行为不具备互操作性,不推荐
NOT RECOMMENDED 依赖此服务。
OpenAPI 描述(OAD)正式描述了 API 的表层及语义。 一个 OAD MAY 可以由单一文档组成,也可以分散至多个文档,各文档可通过URI 引用和隐式连接字段关联。
为保证解析行为明确,OAD 所有文档 MUST 以 OpenAPI 对象或 Schema 对象为根,并 MUST 当作完整文档解析,具体见下一节。
根为其他对象或混杂其他内容的文档 MAY 可被支持,但会有实现自定义行为或潜在未定义行为,详见 附录 G:解析与解析指导。 除非另行说明,本规范假定文档根为 OpenAPI 或 Schema 对象。
对于多文档 OAD,包含 OpenAPI 对象且开始解析的文档称为 OAD 的入口文档。
强烈建议 RECOMMENDED OAD 入口文档命名为 openapi.json 或
openapi.yaml。
OpenAPI 对象 MAY 可嵌入其他格式中,被称为嵌入格式,如 JSON Schema 是以 Schema 对象形式嵌入 OAS。 嵌入格式需定义如何解析嵌入内容,OAS 实现未声明嵌入格式支持时,不应期望能正确解析嵌入式 OAS 内容。
OAD 中每个文档 MUST 完全解析,以定位可能的引用目标。
包括对 JSON
Schema 规范(2020-12草案)的解析要求,并根据URI
相对引用对基础 URI 做修改。
引用目标由字段如 OpenAPI 对象的 $self、Schema
对象的 $id、$anchor 和 $dynamicAnchor 关键字定义。
工具 MUST NOT 在完全解析所有可作为 OAD 部分的文档前,将某引用视为无法解析。
OpenAPI 描述内用于引用、外部文档或如许可证等补充信息的 URI 作为标识符被解析,规范中称为 URI,与API URL区分。注意部分 URI 字段因历史原因名为
url,但描述采用正确的“URI”术语。
如文档解析所述,多个字段可用于将 OpenAPI 文档或 Schema 对象关联到 URI,该 URI 不一定与文档或 schema 的实际位置一致。这样在不同部署环境(如本地文件系统,安全或网络受限环境)下可使用相同引用。
除非另行说明,所有作为 URI 的字段 MAY 接受 [RFC3986] 第 4.2 节 定义的相对引用。
相对 URI 引用需使用合适的基础 URI 解析,MUST 遵循 [RFC3986] 第 5.1.1 – 5.1.4 节,以及 Schema 对象参考 JSON Schema 2020-12 草案第 8.2 节,实际操作可参考 附录 F:基础 URI 解析及引用解析示例。
如 $self 是相对 URI 引用,须按下一个可用基础 URI 来源解析 ([RFC3986] 第 5.1.2 – 5.1.4 节),再用于其他相对
URI 的解析。
若 $self(OpenAPI 对象)或 $id(Schema 对象)缺失或为相对 URI,最常用的基础 URI 来源是获取
URI。工具实现 MAY 支持文档获取,详见 安全注意事项。即使支持获取,也可能受网络配置、服务器不可用(如服务器托管旧版本时新版本在开发中)影响,或因性能不适合获取。因此所有工具实现
SHOULD 允许用户指定文档期望的获取 URI,以便像实际获取一样解析引用。
如 URI 包含片段标识符,则片段应按所引用文档的片段解析机制解析。引用文档为 JSON 或 YAML 时,片段标识符 SHOULD 按 [RFC6901] 作为 JSON 指针解析。
CommonMark 超链接中的相对引用在其渲染上下文中解析,可能与 API 描述上下文不同。
本规范的若干特性要求解析某些非 URI 连接至 OAD 其它部分。
在单文档 OAD 中这些连接可明确解析;在多文档 OAD 下,解析过程属于实现自定义,但须符合本节约束。 部分情况下可用明确的 URI 替代,强烈建议 OAD 作者 RECOMMENDED 使用 URI 以提升工具兼容性。
解析来自引用(非入口)文档的 Components 对象和Tag
对象名称时,建议工具 RECOMMENDED 从入口文档解析而不是当前文档。解析基于
operationId 的 Operation 对象时,建议同时考虑所有已解析文档中的
Operation 对象。
隐式连接解析不影响 URI 解析 及其目标。
更多细节及使用隐式连接的对象和字段清单详见 附录 G:解析与解析指导。
该对象提供 API 元数据。 元数据 MAY 可被客户端在需要时使用,也 MAY 可在编辑或文档生成工具中展示以提升便捷性。
| 字段名 | 类型 | 说明 |
|---|---|---|
| title | string |
REQUIRED。API 标题。 |
| summary | string |
API 简要说明。 |
| description | string |
API 描述。[CommonMark] 语法 MAY 可用于富文本表示。 |
| termsOfService | string |
API 服务条款的 URI。该值 MUST 是 URI 格式。 |
| contact | Contact 对象 | API 的联系信息。 |
| license | License 对象 | API 的许可信息。 |
| version | string |
REQUIRED。OpenAPI 文档版本(与 OpenAPI 规范版本、所描述 API 的版本或描述本身的版本不同)。 |
该对象 MAY 可通过规范扩展扩展。
title: 示例 宠物 商店 应用
summary: 宠物 商店 管理。
description: 这是 一个 宠物 商店 的 示例 服务器。
termsOfService: https://example.com/terms/
contact:
name: API 支持
url: https://www.example.com/support
email: support@example.com
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
version: 1.0.1
暴露的 API 的联系信息。
| 字段名 | 类型 | 说明 |
|---|---|---|
| name | string |
联系人或组织的标识名称。 |
| url | string |
联系信息的 URI。该值 MUST 必须为 URI 形式。 |
string |
联系人或组织的电子邮件地址。该值 MUST 必须为电子邮件地址形式。 |
该对象 MAY 可通过 Specification Extensions 进行扩展。
name: API Support
url: https://www.example.com/support
email: support@example.com
暴露的 API 的许可信息。
| 字段名 | 类型 | 说明 |
|---|---|---|
| name | string |
REQUIRED。API 使用的许可证名称。 |
| identifier | string |
用于 API 的 [SPDX-Licenses] 表达式。identifier
字段与 url 字段互斥。 |
| url | string |
API 所使用许可证的 URI。该值 MUST 必须为 URI 形式。url 字段与
identifier 字段互斥。
|
该对象 MAY 可通过 Specification Extensions 进行扩展。
name: Apache 2.0
identifier: Apache-2.0
表示一个 Server 的对象。
| 字段名 | 类型 | 说明 |
|---|---|---|
| url | string |
REQUIRED。目标主机的 URL。该 URL 支持 Server
Variables,并且 MAY 可以是相对的,用以指示主机位置相对于包含该 Server Object
的文档的服务位置。查询和片段 MUST NOT 不得出现在该 URL 中。若在 URL 模板中以
{braces} 命名变量,则会进行变量替换。
|
| description | string |
用于描述由该 URL 指定的主机的可选字符串。[CommonMark] 语法 MAY 可用于富文本表示。 |
| name | string |
用于引用该 URL 指定主机的可选唯一字符串。 |
| variables | Map[string, Server Variable Object] |
将变量名映射到其值的映射表。该值用于在服务器的 URL 模板中进行替换。 |
该对象 MAY 可通过 Specification Extensions 进行扩展。
API 端点按定义作为位置进行访问,本规范将其描述为 URLs。
除非另有说明,所有作为 URL 的字段 MAY 接受 [RFC3986] 第 4.2 节 定义的相对引用。
由于 API 与 OpenAPI 文档是不同的实体,RFC3986 对 OpenAPI 文档的基础 URI 规则不适用。除非另有说明,相对引用应使用 Server Object 中定义的 URL 作为基础 URL 来解析。注意这些 URL 本身 MAY 相对于引用它们的文档为相对。
假设以下 OpenAPI 文档的检索 URI 为 https://device1.example.com:
openapi: 3.2.0
$self: https://apidescriptions.example.com/foo
info:
title: Example API
version: 1.0
servers:
- url: .
description: The production API on this device
- url: ./test
description: The test API on this device
对于 API URLs,应忽略标识 OpenAPI 文档的 $self 字段,改用检索 URI。这样会得到规范化的生产 URL 为
https://device1.example.com,以及规范化的测试 URL 为
https://device1.example.com/test。
单个服务器可描述为:
url: https://development.gigantic-server.com/v1
description: Development server
name: dev
下面示例展示了如何描述多个服务器,例如在 OpenAPI 对象的 servers:
servers:
- url: https://development.gigantic-server.com/v1
description: Development server
name: dev
- url: https://staging.gigantic-server.com/v1
description: Staging server
name: staging
- url: https://api.gigantic-server.com/v1
description: Production server
name: prod
下面示例展示了如何为服务器配置使用变量:
servers:
- url: https://{username}.gigantic-server.com:{port}/{basePath}
description: The production API server
name: prod
variables:
username:
# note! no enum here means it is an open value
default: demo
description: A user-specific subdomain. Use `demo` for a free sandbox environment.
port:
enum:
- '8443'
- '443'
default: '8443'
basePath:
# open meaning there is the opportunity to use special base paths as assigned by the provider, default is "v2"
default: v2
表示用于服务器 URL 模板替换的 Server Variable 的对象。
服务器 URL 模板由以下 [ABNF] 语法定义。
server-url-template = 1*( literals / server-variable )
server-variable = "{" server-variable-name "}"
server-variable-name = 1*( %x00-7A / %x7C / %x7E-10FFFF ) ; every Unicode character except { and }
literals = 1*( %x21 / %x23-24 / %x26-3B / %x3D / %x3F-5B
/ %x5D / %x5F / %x61-7A / %x7E / ucschar / iprivate
/ pct-encoded)
; any Unicode character except: CTL, SP,
; DQUOTE, "%" (aside from pct-encoded),
; "<", ">", "\", "^", "`", "{", "|", "}"
pct-encoded = "%" HEXDIG HEXDIG
ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
/ %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
/ %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD
/ %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD
/ %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD
/ %xD0000-DFFFD / %xE1000-EFFFD
iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD
此处的 literals、pct-encoded、ucschar 和 iprivate 定义取自
[RFC6570],并结合了 Errata 6937 对 literals 的修正。
每个服务器变量在 URL 模板中 MUST NOT 不得出现多次。
关于构造完整请求 URL 的指导,请参见 Paths Object。
| 字段名 | 类型 | 说明 |
|---|---|---|
| enum | [string] |
当替换选项来自有限集合时使用的字符串枚举。该数组 MUST NOT 不得为空。 |
| default | string |
REQUIRED。用于替换的默认值,若未提供替代值,则 SHALL 发送此默认值。如果定义了 enum,则该值 MUST
必须存在于枚举值中。注意此行为不同于 Schema Object 中的 default
关键字,后者记录接收方的行为而不是将值插入数据中。 |
| description | string |
服务器变量的可选描述。[CommonMark] 语法 MAY 可用于富文本表示。 |
该对象 MAY 可通过 Specification Extensions 进行扩展。
包含一组可重用对象以用于 OAS 的不同方面。所有在 Components Object 中定义的对象,除非在 Components 之外被显式引用,否则不会对 API 产生任何影响。
| 字段名 | 类型 | 说明 |
|---|---|---|
| schemas | Map[string, Schema
Object] |
用于存放可重用 Schema Objects 的对象。 |
| responses | Map[string, Response
Object | Reference Object] |
用于存放可重用 Response Objects 的对象。 |
| parameters | Map[string, Parameter
Object | Reference Object] |
用于存放可重用 Parameter Objects 的对象。 |
| examples | Map[string, Example
Object | Reference Object] |
用于存放可重用 Example Objects 的对象。 |
| requestBodies | Map[string, Request
Body Object | Reference Object] |
用于存放可重用 Request Body Objects 的对象。 |
| headers | Map[string, Header
Object | Reference Object] |
用于存放可重用 Header Objects 的对象。 |
| securitySchemes | Map[string, Security Scheme Object | Reference Object] |
用于存放可重用 Security Scheme Objects 的对象。 |
| links | Map[string, Link Object
| Reference Object] |
用于存放可重用 Link Objects 的对象。 |
| callbacks | Map[string, Callback
Object | Reference Object] |
用于存放可重用 Callback Objects 的对象。 |
| pathItems | Map[string, Path Item
Object] |
用于存放可重用 Path Item Objects 的对象。 |
| mediaTypes | Map[string, Media Type
Object | Reference Object] |
用于存放可重用 Media Type Objects 的对象。 |
该对象 MAY 可通过 Specification Extensions 进行扩展。
上面声明的所有固定字段都是对象,MUST 使用匹配正则表达式 ^[a-zA-Z0-9\.\-_]+$ 的键。
字段名示例:
User
User_1
User_Name
user-name
my.org.User
components:
schemas:
GeneralError:
type: object
properties:
code:
type: integer
format: int32
message:
type: string
Category:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
Tag:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
parameters:
skipParam:
name: skip
in: query
description: number of items to skip
required: true
schema:
type: integer
format: int32
limitParam:
name: limit
in: query
description: max records to return
required: true
schema:
type: integer
format: int32
responses:
NotFound:
description: Entity not found.
IllegalInput:
description: Illegal input for operation.
GeneralError:
description: General Error
content:
application/json:
schema:
$ref: '#/components/schemas/GeneralError'
securitySchemes:
api_key:
type: apiKey
name: api-key
in: header
petstore_auth:
type: oauth2
flows:
implicit:
authorizationUrl: https://example.org/api/oauth/dialog
scopes:
write:pets: modify pets in your account
read:pets: read your pets
保存指向各个端点及其操作的相对路径。该路径会附加到来自 Server Object 的 URL 上以构造完整的 URL。由于 访问控制列表(ACL)约束,Paths Object MAY 可以为空。
| 字段模式 | 类型 | 描述 |
|---|---|---|
| /{path} | Path Item 对象 | 指向单个端点的相对路径。字段名 MUST 以正斜杠(/)开头。来自 Server Object 的 url
字段在解析并替换模板变量后,会将该路径追加(不进行相对 URL 解析)到其上以构造完整的 URL。允许使用 路径模板化。在匹配 URL
时,具体(非模板化的)路径会先于其模板化的对应项被匹配。具有相同层级但模板名称不同的模板化路径 MUST NOT
共存,因为它们是相同的。若出现歧义匹配,由工具决定使用哪一个。 |
该对象 MAY 可通过 规范扩展 进行扩展。
路径模板化指使用以大括号({})分隔的模板表达式,将 URL 路径的一部分标记为可通过路径参数替换的部分。
路径中的每个模板表达式 MUST 对应于在 Path Item 本身和/或该 Path Item 的每个 Operation 中包含的路径参数。例外情况是当 Path Item 为空(例如由于 ACL 约束),则不要求存在匹配的路径参数。
这些路径参数的值 MUST NOT 包含任何未转义的“通用语法”字符,参见 [RFC3986] 第 3
节:正斜杠(/)、问号(?)或井号(#)。有关转义字符的更多指导,请参阅 URL 百分号编码。
路径模板化由下列 [ABNF] 语法定义
path-template = "/" *( path-segment "/" ) [ path-segment ]
path-segment = 1*( path-literal / template-expression )
path-literal = 1*pchar
template-expression = "{" template-expression-param-name "}"
template-expression-param-name = 1*( %x00-7A / %x7C / %x7E-10FFFF ) ; every Unicode character except { and }
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
此处的 pchar、unreserved、pct-encoded 与 sub-delims
定义取自 [RFC3986]。path-template
直接源自 RFC 3986,第 3.3 节。
每个模板表达式在单一路径模板中 MUST NOT 出现多于一次。
另见 附录 C:使用基于 RFC6570 的序列化 以获取更多指导。
假设存在如下路径,如果使用,则具体定义 /pets/mine 将优先匹配:
/pets/{petId}
/pets/mine
以下路径被视为相同且无效:
/pets/{petId}
/pets/{name}
以下情况可能导致歧义解析:
/{entity}/me
/books/{id}
/pets:
get:
description: Returns all pets from the system that the user has access to
responses:
'200':
description: A list of pets.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/pet'
描述单一路径上可用的操作。由于 ACL 约束,Path Item MAY 为空。该路径本身仍会在文档查看器中显示,但查看者将无法知道哪些操作和参数可用。
| 字段名 | 类型 | 描述 |
|---|---|---|
| $ref | string |
允许对该 Path Item 进行引用定义。该值 MUST 必须是 URI 形式,被引用的结构 MUST 必须是 Path Item Object
的形式。如果在已定义的对象和被引用的对象中都出现 Path Item Object 字段,则行为未定义。参见解析 相对引用
的规则。 注:在将来版本的规范中, $ref 与相邻属性的行为可能会更改,以使其与 Reference Object 的行为更为一致。
|
| summary | string |
一个可选的字符串摘要,旨在适用于该路径中的所有操作。 |
| description | string |
一个可选的字符串描述,旨在适用于该路径中的所有操作。可以使用 [CommonMark] 语法来进行富文本表示,MAY 使用。 |
| get | Operation 对象 | 该路径上 GET 操作的定义。 |
| put | Operation 对象 | 该路径上 PUT 操作的定义。 |
| post | Operation 对象 | 该路径上 POST 操作的定义。 |
| delete | Operation 对象 | 该路径上 DELETE 操作的定义。 |
| options | Operation 对象 | 该路径上 OPTIONS 操作的定义。 |
| head | Operation 对象 | 该路径上 HEAD 操作的定义。 |
| patch | Operation 对象 | 该路径上 PATCH 操作的定义。 |
| trace | Operation 对象 | 该路径上 TRACE 操作的定义。 |
| query | Operation 对象 | 该路径上 QUERY 操作的定义,按最新的 IETF 草案(撰写本文时为 draft-ietf-httpbis-safe-method-w-body-08)或其 RFC 后续版本 的定义。 |
| additionalOperations | Map[string, Operation
对象] |
该路径上额外操作的映射。映射的键是要在请求中发送的 HTTP 方法,其大小写与实际发送一致。该映射 MUST NOT
包含可以由其他固定字段(具有 Operation Object 值)定义的方法的条目(例如,不应包含 POST 条目,因为
post 字段用于该方法)。
|
| servers | [Server Object] | 用于为该路径下所有操作提供服务的替代 servers 数组。如果在 OpenAPI Object
级别指定了 servers 数组,则会被此值覆盖。 |
| parameters | [Parameter Object | Reference Object] | 适用于该路径下所有操作的参数列表。这些参数可以在操作级别被覆盖,但不能被删除。该列表 MUST NOT
包含重复参数。唯一参数由 name 和 location
的组合定义。该列表可以使用 Reference Object 链接到在 OpenAPI Object 的
components.parameters 中定义的参数。 |
该对象 MAY 可通过 规范扩展 进行扩展。
get:
description: Returns pets based on ID
summary: Find pets by ID
operationId: getPetsById
responses:
'200':
description: pet response
content:
'*/*':
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
default:
description: error payload
content:
text/html:
schema:
$ref: '#/components/schemas/ErrorModel'
parameters:
- name: id
in: path
description: ID of pet to use
required: true
schema:
type: array
items:
type: string
style: simple
additionalOperations:
COPY:
description: Copies pet information based on ID
summary: Copies pets by ID
operationId: copyPetsById
responses:
'200':
description: pet response
content:
'*/*':
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
default:
description: error payload
content:
text/html:
schema:
$ref: '#/components/schemas/ErrorModel'
描述路径上的单个 API 操作。
| 字段名 | 类型 | 描述 |
|---|---|---|
| tags | [string] |
用于 API 文档控制的标签列表。标签可用于按资源或其他任意分类对操作进行逻辑分组。 |
| summary | string |
对该操作所做内容的简短摘要。 |
| description | string |
对操作行为的详细说明。可以使用 [CommonMark] 语法来进行富文本表示,MAY 使用。 |
| externalDocs | 外部文档对象 | 该操作的补充外部文档。 |
| operationId | string |
用于标识操作的唯一字符串。该 id 在 API 中所有操作之间 MUST 保持唯一。operationId 值是区分大小写的。工具和库 MAY 使用 operationId 来唯一标识一个操作,因此建议遵循常见的编程命名约定。 |
| parameters | [Parameter Object | Reference Object] | 适用于该操作的参数列表。如果参数已在 Path Item 中定义,新定义将覆盖它但永远不能移除它。该列表
MUST NOT 包含重复参数。唯一参数由 name 和 location 的组合定义。该列表可以使用 Reference Object 链接到在 OpenAPI Object 的
components.parameters 中定义的参数。
|
| requestBody | Request Body Object | Reference Object | 适用于该操作的请求体。对于 HTTP 规范明确为请求体定义语义的 HTTP 方法(参见 HTTP 规范 [RFC9110] 第 9.3
节),requestBody 完全受支持。在其他 HTTP 规范不鼓励包含消息内容的情况(例如 GET 和 DELETE),允许使用
requestBody,但其语义并不明确,SHOULD 尽可能避免。
|
| responses | Responses Object | 执行该操作后可能返回的响应列表。 |
| callbacks | Map[string, Callback
Object | Reference Object] |
与父操作相关的可能的带外回调的映射。键是 Callback Object 的唯一标识符。映射中的每个值都是描述 API 提供者可能发起的请求以及预期响应的 Callback Object。 |
| deprecated | boolean |
声明此操作已被弃用。消费者 SHOULD 避免使用被声明的操作。默认值为 false。 |
| security | [Security Requirement Object] | 声明可用于此操作的安全机制。该值列表包含可替代使用的 Security Requirement Objects。只需满足其中一个 Security Requirement
Object 即可授权请求。要使安全成为可选项,可以在数组中包含一个空的安全需求({})。此定义会覆盖任何声明的顶级 security。要移除顶级安全声明,可以使用空数组。 |
| servers | [Server Object] | 为此操作提供服务的替代 servers 数组。如果在 Path Item
Object 或 OpenAPI Object 级别指定了 servers
数组,它们将被此值覆盖。 |
该对象 MAY 可通过 规范扩展 进行扩展。
tags:
- pet
summary: Updates a pet in the store with form data
operationId: updatePetWithForm
parameters:
- name: petId
in: path
description: ID of pet that needs to be updated
required: true
schema:
type: string
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
name:
description: Updated name of the pet
type: string
status:
description: Updated status of the pet
type: string
required:
- status
responses:
'200':
description: Pet updated.
content:
application/json: {}
application/xml: {}
'405':
description: Method Not Allowed
content:
application/json: {}
application/xml: {}
security:
- petstore_auth:
- write:pets
- read:pets
允许引用外部资源以获取扩展文档。
| 字段名 | 类型 | 描述 |
|---|---|---|
| description | string |
目标文档的描述。可以使用 [CommonMark] 语法来进行富文本表示(MAY)。 |
| url | string |
REQUIRED。目标文档的 URI。此项 MUST 必须采用 URI 的形式。 |
该对象 MAY 可通过 规范扩展 进行扩展。
description: Find more info here
url: https://example.com
描述单个操作参数。
有关百分号编码问题的详细探讨(包括与 application/x-www-form-urlencoded 查询字符串格式的交互),请参阅 附录 E。
由 in 字段指定的参数位置有五种:
/items/{itemId} 中,路径参数是 itemId。
/items?id=### 中,查询参数是 id;MUST NOT 与 in: "querystring" 参数在同一操作(或该操作的
path-item)中同时出现。content
字段指定,通常使用媒体类型 application/x-www-form-urlencoded 并使用 Encoding Objects,与该媒体类型的请求体相同;MUST NOT
出现多次,并且 MUST NOT 与任何 in: "query" 参数在同一操作(或该操作的
path-item)中同时出现。参数的序列化规则通过两种方式中的一种指定。Parameter Objects MUST 包含 content 字段或
schema 字段,但不能同时包含两者。有关将各种类型的值转换为字符串表示的讨论,请参阅 附录 B。
这些字段 MAY 与 content 或 schema 一起使用。
example 与 examples 字段互斥;有关验证要求的指导,请参阅 Working with Examples。
| 字段名 | 类型 | 描述 |
|---|---|---|
| name | string |
REQUIRED。参数的名称。参数名称区分大小写。
|
| in | string |
REQUIRED。参数的位置。可能的值为
"query"、"querystring"、"header"、"path"
或 "cookie"。
|
| description | string |
参数的简短描述。可以包含使用示例。可以使用 [CommonMark] 语法进行富文本表示(MAY)。 |
| required | boolean |
确定此参数是否为必需。如果参数位置为 "path",此字段为 REQUIRED,其值 MUST 为
true。否则,该字段 MAY 包含,默认值为 false。
|
| deprecated | boolean |
指定参数已被弃用,应逐步停止使用(SHOULD)。默认值为 false。 |
| allowEmptyValue | boolean |
如果为 true,客户端 MAY 传递空字符串作为参数值(代替完全省略参数),服务器 SHOULD 将其解释为参数未使用。默认值为 false。如果使用了 style,且 序列化行为为 n/a(无法序列化),则
allowEmptyValue 的值 SHALL 被忽略。该字段与参数的 Schema Object 之间的交互由实现定义。此字段仅对 query
参数有效。已弃用:不建议使用该字段(NOT RECOMMENDED),并且可能在将来版本中被移除。 |
| example | Any | 参数的可能值示例;参见 Working With Examples。 |
| examples | Map[ string, Example Object | Reference Object] |
参数的可能值示例集合;参见 Working With Examples。 |
该对象 MAY 可通过 规范扩展 进行扩展。
注意,虽然如果 in 为 "header" 时 "Cookie" 作为 name
并非被禁止,但这样定义 cookie 参数的效果是未定义的;应使用 in: "cookie"。
对于简单场景,schema 和 style 可以描述参数的结构和语法。
这些字段 MUST NOT 与 in: "querystring" 一起使用。
对于具有 schema 且 in: "header" 或 in: "cookie", style: "cookie"
的参数,需要注意:
在这些情况下,实现 MUST 原样传递值,而不是尝试对其进行引用或转义,因为头和 cookie 的引用规则与转义约定差异太大,无法自动处理;有关引用和转义的指导,请参见 附录 D。
| 字段名 | 类型 | 描述 |
|---|---|---|
| style | string |
描述参数值将如何根据参数类型进行序列化。默认值(基于 in 的取值):对于 "query" 为
"form";对于 "path" 为 "simple";对于
"header" 为 "simple";对于 "cookie" 为
"form"(出于兼容性原因;注意应与 in: "cookie" 一起使用
style: "cookie";详见 附录 D)。
|
| explode | boolean |
当为 true 时,类型为 array 或 object
的参数会为数组的每个值或对象的每个键值对产生独立的参数。对于其他类型或当 style 为 "deepObject"
时,此字段无效。若 style 为 "form" 或 "cookie",默认值为
true;对于其他样式,默认值为 false。
|
| allowReserved | boolean |
当为 true 时,参数值按 [RFC6570] 定义的保留扩展进行序列化(参见 Section
3.2.3),这允许 RFC3986 的保留字符集以及百分号编码的三元组保持不变,同时对所有其他不允许的字符进行百分号编码(包括百分号
%,若其不属于百分号编码三元组)。应用仍需对目标位置或媒体类型不允许的保留字符进行百分号编码,或对 本规范不允许出现在路径中的字符 进行处理;详见 URL 百分号编码。默认值为
false。此字段仅适用于会自动进行百分号编码的 in 与 style 值。
|
| schema | Schema Object | 定义参数使用类型的 schema。 |
另请参见 附录 C:使用基于 RFC6570 的序列化 以获取更多指导。
对于更复杂的场景,content 字段可定义参数的媒体类型和 schema,并提供其使用示例。
对于 in: "querystring" 和 application/x-www-form-urlencoded 的使用,请参见 Encoding the
x-www-form-urlencoded Media Type。
| 字段名 | 类型 | 描述 |
|---|---|---|
| content | Map[string, Media Type Object | Reference Object] |
包含参数表示形式的映射。键是媒体类型,值描述该媒体类型。该映射 MUST 只能包含一项条目。 |
为了支持常见的简单参数序列化方式,定义了一组 style 值。表中未表示的组合是不允许的。
style |
type |
in |
说明 |
|---|---|---|---|
matrix |
primitive, array, object |
path |
路径样式参数,由 [RFC6570] 定义的第 3.2.7 节 所描述。 |
label |
primitive, array, object |
path |
标签样式参数,由 RFC6570 定义(参见 3.2.5 节)。 |
simple |
primitive, array, object |
path, header |
简单样式参数,由 RFC6570 定义(参见 3.2.2
节)。此选项替代 OpenAPI 2.0 中的 collectionFormat 的 csv 值。 |
form |
primitive, array, object |
query, cookie |
表单样式参数,由 RFC6570 定义(参见 3.2.8 节)。此选项在
OpenAPI 2.0 中替代了 collectionFormat 的 csv(当 explode
为 false)或 multi(当 explode 为 true)。 |
spaceDelimited |
array, object |
query |
以空格分隔的数组值或对象属性与值。此选项替代 OpenAPI 2.0 中 collectionFormat 等于 ssv
的情形。 |
pipeDelimited |
array, object |
query |
以竖线(|)分隔的数组值或对象属性与值。此选项替代 OpenAPI 2.0 中 collectionFormat 等于
pipes 的情形。
|
deepObject |
object |
query |
允许使用表单参数表示具有标量属性的对象。数组或对象属性的表示未定义(但参见 扩展对 Querystring 格式的支持 获取替代方案)。 |
cookie |
primitive, array, object |
cookie |
与 form 类似,但遵循 [RFC6265]
的 Cookie 语法规则,表示 name=value 对由分号加单空格分隔(例如
n1=v1; n2=v2),且不应用百分号编码或其他转义;需要任何转义的值 MUST
以转义形式提供。
|
所有 API URL MUST 能够根据 [RFC3986] 的规则成功解析并进行百分号解码。
以 application/x-www-form-urlencoded 格式的内容,包括由具有 in: "query" 的 Parameter Objects 生成的查询字符串,也 MUST 能够根据
[WHATWG-URL] 的规则成功解析并进行百分号解码,其中将未百分号编码的 +
视为已转义的空格字符。
这些要求以百分号解码规则来指定,这些规则在适用于 URI 的不同标准版本之间保持一致的容错性。
在若干场景下会执行百分号编码:
执行百分号编码时,最安全的方法是对 RFC3986 的“unreserved”集合之外的所有字符进行百分号编码;对于
form-urlencoded,还应对波浪号(~)进行百分号编码,以与源自 RFC1738 的历史要求保持一致。本规范中的示例采用了这种做法。
对于 form-urlencoded,尽管 [WHATWG-URL] 的算法要求将空格转义为 +,将空格百分号编码为
%20 也符合上述要求。在使用 RFC6570 的默认(非保留)表单样式扩展时,本规范示例会更倾向于使用 %20,否则使用
+。
当保留字符用于保留用途(例如在 form-urlencoded 中的 &=+,或在 RFC6570 扩展中用于分隔非爆炸数组与对象值的
,)时,不应对这些保留字符进行百分号编码(MUST NOT)。通过手动百分号编码将未编码的分隔符插入数据(包括通过
RFC6570 的保留扩展规则)所得结果是未定义的,并且可能导致实现无法将其解析回正确的数据结构。在某些情况下,例如将 / 插入路径参数值,本规范 明确禁止 这样做。
另见:
本节的规则适用于 Parameter 与 Header 对象,它们使用相同的机制。
在展示序列化示例时,例如在 Example Object 的 serializedValue 或
externalValue 字段中,在大多数情况下应显示实际序列化后的值,包含所有相关的百分号编码或其他编码/转义,并包括由 style 与
explode 产生的任何分隔符。
在名称本身是构造序列化的一部分的情况下(例如由 style: "form" 生成的 name=value 对,或
style: "simple", explode: true 的组合),必须包含名称以及名称与值之间的任何分隔符(MUST)。
matrix 与 label 样式会产生始终为有效序列化一部分的前导分隔符,该分隔符必须包含。对应
style: "form" 的 RFC6570 运算符会生成 ? 或 &
之一作为前导分隔符,具体取决于所使用的语法。由于是否应使用哪种分隔符依赖于参数在查询字符串中的位置以及它是在 URI 中还是在
application/x-www-form-urlencoded 内容中,因此在单个参数或媒体类型文档的示例中不得包含该前导分隔符(MUST NOT)。对于 in: "cookie", style: "form",既不是
& 也不是 ? 分隔符适用;详见 附录 D:序列化头和 Cookies。
对于头部,序列化中不得包含头名(MUST NOT),因为头名从不属于 RFC6570 导出的结果的一部分。然而,由
style: "simple", explode: "true" 生成的名称会作为头值的一部分出现,但不是作为独立头。关于 Set-Cookie
响应头示例的特殊规则,请参见 Header Object。
假设名为 color 的参数有下列值之一,箭头右侧的内容表示在 Example Object 的 dataValue 字段中会显示的值:
string -> "blue"
array -> ["blue", "black", "brown"]
object -> { "R": 100, "G": 200, "B": 150 }
下表展示了不同值的序列化示例(如在 Example Object 的 serializedValue 字段中所示)。
allowEmptyValue 字段无关。undefined 列替代了以前规范中的 empty 列,以更好地与 RFC6570 的术语对齐,RFC6570 描述了包括但不限于
null 的“未定义”值具有特殊处理;值得注意的是,空字符串并非未定义。
form 与非 RFC6570 的查询字符串样式 spaceDelimited、pipeDelimited
和 deepObject,请参见 附录
C,了解如何从多个参数构造查询字符串,以及参见 附录
D,了解关于 form 与 cookie 参数的警告。|(%7C)、[(%5B)和
](%5D)在某些环境中似乎可用但并不合规的原因。
style |
explode |
undefined |
string |
array |
object |
|---|---|---|---|---|---|
| matrix | false | ;color | ;color=blue | ;color=blue,black,brown | ;color=R,100,G,200,B,150 |
| matrix | true | ;color | ;color=blue | ;color=blue;color=black;color=brown | ;R=100;G=200;B=150 |
| label | false | . | .blue | .blue,black,brown | .R,100,G,200,B,150 |
| label | true | . | .blue | .blue.black.brown | .R=100.G=200.B=150 |
| simple | false | empty | blue | blue,black,brown | R,100,G,200,B,150 |
| simple | true | empty | blue | blue,black,brown | R=100,G=200,B=150 |
| form | false | color= | color=blue | color=blue,black,brown | color=R,100,G,200,B,150 |
| form | true | color= | color=blue | color=blue&color=black&color=brown | R=100&G=200&B=150 |
| spaceDelimited | false | n/a | n/a | color=blue%20black%20brown | color=R%20100%20G%20200%20B%20150 |
| spaceDelimited | true | n/a | n/a | n/a | n/a |
| pipeDelimited | false | n/a | n/a | color=blue%7Cblack%7Cbrown | color=R%7C100%7CG%7C200%7CB%7C150 |
| pipeDelimited | true | n/a | n/a | n/a | n/a |
| deepObject | n/a | n/a | n/a | n/a | color%5BR%5D=100&color%5BG%5D=200&color%5BB%5D=150 |
| cookie | false | color= | color=blue | color=blue,black,brown | color=R,100,G,200,B,150 |
| cookie | true | color= | color=blue | color=blue; color=black; color=brown | R=100; G=200; B=150 |
许多框架定义了用于复杂值的查询字符串语法,例如在参数名后追加数组索引或表示多层嵌套对象,这些超出了 deepObject 的能力范围。
由于这些并非标准且常互相冲突,OAS 并不尝试直接支持它们。对于使用 in: "querystring" 的此类格式,有两种可行途径:
content 并将媒体类型设为 text/plain,schema 为 type: "string",并在
OpenAPI 之外定义格式。虽然这需要更多的工作来描述和构造或解析该格式(从 OpenAPI 视角看这是一个普通字符串),但它提供了最灵活的选项。一个包含 64 位整数数组的头参数示例:
name: X-Token
in: header
description: token to be passed as a header
required: true
schema:
type: array
items:
type: integer
format: int64
style: simple
examples:
Tokens:
dataValue:
- 12345678
- 90099
serializedValue: "12345678,90099"
一个使用爆炸对象的 cookie 参数(对于 style: "cookie" 默认即为爆炸):
name: cookie
in: cookie
style: cookie
schema:
type: object
properties:
greeting:
type: string
code:
type: integer
minimum: 0
examples:
Object:
description: |
Note that the comma (,) has been pre-percent-encoded
to "%2C" in the data, as it is forbidden in
cookie values. However, the exclamation point (!)
is legal in cookies, so it can be left unencoded.
dataValue:
greeting: Hello%2C world!
code: 42
serializedValue: "greeting=Hello%2C world!; code=42"
一个依赖于默认 style: "form" 的百分号编码行为的 cookie 参数示例:
name: greeting
in: cookie
schema:
type: string
examples:
Greeting:
description: |
Note that in this approach, RFC6570's percent-encoding
process applies, so unsafe characters are not
pre-percent-encoded. This results in all non-URL-safe
characters, rather than just the one non-cookie-safe
character, getting percent-encoded.
dataValue: Hello, world!
serializedValue: "greeting=Hello%2C%20world%21"
一个字符串类型的路径参数示例:
name: username
in: path
description: username to fetch
required: true
schema:
type: string
examples:
"Edsger Dijkstra":
dataValue: edijkstra
serializedValue: edijkstra
Diṅnāga:
dataValue: diṅnāga
serializedValue: di%E1%B9%85n%C4%81ga
Al-Khwarizmi:
dataValue: "الخوارزميّ"
serializedValue: "%D8%A7%D9%84%D8%AE%D9%88%D8%A7%D8%B1%D8%B2%D9%85%D9%8A%D9%91"
一个可选的字符串查询参数,允许通过重复查询参数来提供多个值(注意这里使用 "%20" 代替空格,因为这是 RFC6570 的处理方式;关于使用 +
表示空格的说明,请参见 附录 E):
name: thing
in: query
required: false
schema:
type: array
items:
type: string
style: form
explode: true
examples:
ObjectList:
dataValue:
- one thing
- another thing
serializedValue: "thing=one%20thing&thing=another%20thing"
一个自由形式的查询参数示例,允许任意的 type: "integer" 参数:
in: query
name: freeForm
schema:
type: object
additionalProperties:
type: integer
style: form
examples:
Pagination:
dataValue:
page: 4
pageSize: 50
serializeValue: page=4&pageSize=50
一个使用 content 定义序列化的复杂参数示例,展示了多个层级和类型的示例以清晰说明示例用法 — 注意 dataValue
在两个层级是相同的,通常不需要在两个位置都显示,但 serializedValue 不同:
in: query
name: coordinates
content:
application/json:
schema:
type: object
required:
- lat
- long
properties:
lat:
type: number
long:
type: number
examples:
dataValue:
lat: 10
long: 60
serializedValue: '{"lat":10,"long":60}'
examples:
dataValue:
lat: 10
long: 60
serializedValue: coordinates=%7B%22lat%22%3A10%2C%22long%22%3A60%7D
一个使用媒体类型对象管理的查询字符串参数示例,展示了按 application/x-www-form-urlencoded 媒体类型规则处理空格(用
+ 编码)而非 RFC6570 的处理(用 %20 编码);有关此区别的更多指导,请参见 附录 E。在媒体类型和参数级别都展示示例以强调,由于
application/x-www-form-urlencoded 定义上即适用于查询字符串,因此对序列化的媒体类型值不再进行额外的编码或转义:
in: querystring
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
foo:
type: string
bar:
type: boolean
examples:
spacesAndPluses:
description: Note handling of spaces and "+" per media type.
dataValue:
foo: a + b
bar: true
serializedValue: foo=a+%2B+b&bar=true
examples:
spacesAndPluses:
description: |
Note that no additional percent encoding is done, as this
media type is URI query string-ready by definition.
dataValue:
foo: a + b
bar: true
serializedValue: foo=a+%2B+b&bar=true
一个将整个字符串使用 JSON 的查询字符串参数(不是作为单个查询参数值)。在两个层级都展示 dataValue
字段以完整说明两种提供示例的方式。如下所示,这在实践中是冗余的且不必同时进行:
in: querystring
name: json
content:
application/json:
schema:
type: object
properties:
numbers:
type: array
items:
type: integer
flag:
type: [boolean, "null"]
examples:
TwoNoFlag:
description: Serialize with minimized whitespace
dataValue:
numbers:
- 1
- 2
flag: null
serializedValue: '{"numbers":[1,2],"flag":null}'
examples:
TwoNoFlag:
dataValue:
numbers:
- 1
- 2
flag: null
serializedValue: "%7B%22numbers%22%3A%5B1%2C2%5D%2C%22flag%22%3Anull%7D"
假设路径为 /foo,服务器为 https://example.com,则包含来自 serializedValue
的值的完整 URL 如下:
https://example.com/foo?%7B%22numbers%22%3A%5B1%2C2%5D%2C%22flag%22%3Anull%7D
一个使用 JSONPath 的查询字符串参数示例。注意在此示例中我们不仅不重复
dataValue,而且使用简写的 example,因为 application/jsonpath
的值是一个字符串,在媒体类型级别按原样序列化:
in: querystring
name: selector
content:
application/jsonpath:
schema:
type: string
example: $.a.b[1:1]
examples:
Selector:
serializedValue: "%24.a.b%5B1%3A1%5D"
由于截至撰写时尚无将 JSON Schema 数据模型与 JSONPath 建立映射的 注册,该字符串允许结构的细节需要通过可读的 description 字段传达,或通过
OpenAPI 描述之外的机制(例如用于被查询数据结构的 JSON Schema)来表达。
假设路径为 /foo 且服务器为 https://example.com,则包含来自 serializedValue
的值的完整 URL 如下:
https://example.com/foo?%24.a.b%5B1%3A1%5D
描述单个请求体。
| 字段名 | 类型 | 描述 |
|---|---|---|
| description | string |
请求体的简要描述。可以包含使用示例。可使用 [CommonMark] 语法来进行富文本表示(MAY)。 |
| content | Map[string, Media
Type Object | Reference Object] |
REQUIRED。请求体的内容。键为媒体类型或 media type
range,值描述该媒体类型。该映射SHOULD
至少包含一项;如果不包含,行为由实现定义。对于匹配多个键的请求,仅最具体的键适用,例如 "text/plain" 会覆盖
"text/*"。
|
| required | boolean |
确定请求中是否必须包含请求体。默认值为 false。 |
该对象 MAY 可通过 Specification Extensions 进行扩展。
带有引用 schema 定义的请求体示例。
description: user to add to the system
content:
application/json:
schema:
$ref: '#/components/schemas/User'
examples:
user:
summary: User example
externalValue: https://foo.bar/examples/user-example.json
application/xml:
schema:
$ref: '#/components/schemas/User'
examples:
user:
summary: User example in XML
externalValue: https://foo.bar/examples/user-example.xml
text/plain:
examples:
user:
summary: User example in plain text
externalValue: https://foo.bar/examples/user-example.txt
'*/*':
examples:
user:
summary: User example in other format
externalValue: https://foo.bar/examples/user-example.whatever
每个 Media Type Object 描述与其键所标识的媒体类型一致的内容结构。 可以使用多个 Media Type Object 来描述可出现在多种不同媒体类型中的内容。
当提供 example 或 examples 时,示例 SHOULD 与指定的 schema
匹配,并采用媒体类型及其编码所指定的正确格式。
example 与 examples 字段互斥。
有关以不同方式指定示例(包括非 JSON/YAML 值)的更多指南,请参见 Working With Examples。
| 字段名 | 类型 | 描述 |
|---|---|---|
| schema | Schema Object | 描述请求、响应、参数或头的完整内容的 schema。 |
| itemSchema | Schema Object | 描述 顺序媒体类型 中每个项的 schema。 |
| example | Any | 该媒体类型的示例;参见 Working With Examples。 |
| examples | Map[ string, Example
Object | Reference Object] |
该媒体类型的示例集合;参见 Working With Examples。 |
| encoding | Map[string, Encoding
Object] |
属性名与其编码信息之间的映射,如 按名称编码 所定义。仅当媒体类型为
multipart 或 application/x-www-form-urlencoded
时,encoding 字段 SHALL 生效。如果未为某属性提供 Encoding
Object,则行为由 Encoding Object 的默认值决定。若存在 prefixEncoding 或
itemEncoding,则该字段 MUST NOT 出现。
|
| prefixEncoding | [Encoding Object] | 按位置的编码信息数组,如 按位置编码 所定义。仅当媒体类型为
multipart 时,prefixEncoding 字段 SHALL
生效。如果未为某属性提供 Encoding Object,则行为由 Encoding Object 的默认值决定。若存在 encoding,则该字段
MUST NOT 出现。
|
| itemEncoding | Encoding Object | 为多个数组项提供编码信息的单个 Encoding Object,如 按位置编码 所定义。仅当媒体类型为
multipart 时,itemEncoding 字段 SHALL
生效。如果未为某属性提供 Encoding Object,则行为由 Encoding Object 的默认值决定。若存在 encoding,则该字段
MUST NOT 出现。
|
该对象 MAY 可通过 Specification Extensions 进行扩展。
媒体类型通过 IANA media types registry 以公开注册的方式记录,注册流程记录在 [RFC6838] 中。
API 有时也会定义私有媒体类型,例如 GitHub 的 application/vnd.github.v3+json(未注册),以及其他媒体类型如
application/schema+json 在被正式注册前已经被广泛使用。
有关在多种媒体类型下使用 schemas 的解析与序列化指南,请参见 Parsing and Serializing(位于 Schema Object 下)。
OpenAPI Initiative 维护了一个 Media Type Registry,汇总了本规范期望支持的媒体类型并索引了哪些章节讨论了哪些媒体类型。该注册表还链接到 IANA 注册(若存在)以及与每种媒体类型相关的最重要的规范文档。 在该注册表中作为扩展或为后续版本添加的任何附加媒体类型,MAY 被本版本 OAS 的实现所支持。
schema 字段 MUST 应用于完整内容,该完整内容由媒体类型和上下文(Request Body Object、Response
Object、Parameter Object 或 Header
Object)定义。
由于这需要将内容完整加载到内存中,因此对流式内容会带来挑战。
在客户端需要决定何时停止读取的用例尤其具有挑战性,因为流没有明确定义的结束。
在本规范中,顺序媒体类型 定义为任何由重复结构组成且没有头部、尾部、信封或其它元数据附加到序列之外的媒体类型。
一些顺序媒体类型示例(包括一些未在 IANA 注册但常用的)为:
application/jsonl
application/x-ndjson
application/json-seq
application/geo+json-seq
text/event-stream
multipart/mixed
在前面三个示例中,重复结构为任何 JSON value。第四个重复的是
application/geo+json 结构化值,而 text/event-stream
则重复与服务器发送事件相关的自定义文本格式。最后列出的 multipart/mixed 提供任意媒体类型文档的有序列表,有时用于流式传输。
注意尽管 multipart 格式在技术上允许前言和结尾,但 RFC 指示应忽略它们,使其实际作为注释,本规范不对其进行建模。
实现 MUST 支持将顺序媒体类型映射到 JSON Schema 数据模型,方法是将其视为按相同顺序排列的数组中的值。
关于在流式上下文中处理顺序媒体类型的更多信息,包括对 text/event-stream 内容的特殊考虑,请参见 Complete vs Streaming Content。对于
multipart 类型,也请参见 Encoding By Position。
itemSchema 字段用于支持顺序媒体类型的流式用例,itemEncoding 则为流式的 按位置的 multipart 媒体类型 提供对应的编码机制。
与应用于完整内容的 schema 不同(按 顺序媒体类型
节所述将其视为数组),itemSchema MUST
应用于流中每个项,这支持在从流中读取时对每个项进行逐个处理。
schema 与 itemSchema 都 MAY 在同一 Media Type
Object 中使用。但这样做相较于在 schema 字段中使用 items 关键字通常并无显著优势。
maxLength 关键字 MAY
用于设置由字符串数据(包括编码的二进制数据)或未编码的二进制数据组成的流式有效载荷的预计上限长度。对于未编码的二进制数据,长度以八位字节(octets)计。
在这种用例中,maxLength MAY 在常规 JSON Schema 验证之外被实现,因为 JSON
Schema 并不直接适用于二进制数据,并且对编码的二进制流将其完整存于内存中可能不可行。
对于 text/event-stream,实现 MUST 在根据 text/event-stream
specification 解析事件流后处理事件数据,包括忽略某些字段(包括注释)和/或值的所有指导,以及合并跨多行拆分的值的规则。
字段值类型 MUST 按 text/event-stream 规范的规定处理(例如 retry
字段值被建模为预期为 JSON Schema type: integer 的 JSON 数字),而未给出显式值类型的字段 MUST 作为字符串处理。
一些 text/event-stream 的使用者在字段值中使用 JSON 格式,尤其是 data 字段。对于此类字符串编码数据的内容,请使用
JSON Schema 的关键词(尤其是 contentMediaType 与
contentSchema)来描述并验证这些字段,以提供比基于字符串的验证(如 pattern)更详尽的描述与验证。注意
contentSchema 并非默认被自动验证(另见本规范的 Non-validating constraint keywords 部分)。
下面的 Schema Object 是截至撰写本文时由 [HTML] 规范所记录的 text/event-stream 媒体类型的通用 schema:
type: object
required:
- data
properties:
data:
type: string
event:
type: string
id:
type: string
retry:
type: integer
minimum: 0
这些编码字段定义了如何将每个 Encoding Object 映射到数据中的具体值。 每个字段都有其可使用的媒体类型集;对于所有其它媒体类型,这三者在实现上 SHALL 被忽略。
encoding 字段的行为旨在支持 Web 表单,因此仅为结构为允许重复值的名-值对的媒体类型定义,最显著的是
application/x-www-form-urlencoded 与 multipart/form-data。
要使用 encoding 字段,字段下的每个键 MUST 在属性中存在;没有对应属性的
encoding 条目 SHALL 被忽略。
数组属性 MUST 通过对数组的每个项应用给定的 Encoding Object
来处理,以生成每个数组项对应的一个已编码值,且这些已编码值使用相同的 name,这与 [RFC7578] 第 4.3 节 建议的为表单字段提供多个值的做法一致。
对于顶层非数组属性以及顶层数组内的值(包括数组值)的所有其他值类型,应将 Encoding Object 应用于整个值。
这些名-值对在目标媒体类型中的顺序由实现定义。
对于 application/x-www-form-urlencoded,编码键 MUST 映射到参数名称,值按照
Encoding Object 的规则生成。有关使用与不使用 encoding 字段的指导与示例,请参见
Encoding the
x-www-form-urlencoded Media Type。
对于 multipart,编码键 MUST 映射到每个部分的
Content-Disposition: form-data 头的 name 参数,如 [RFC7578] 所定义。关于非
ASCII 部分名称的指导,请参见 RFC7578 的 第 5 节。
有关带或不带 encoding 字段的更多指导与示例,请参见 Encoding
multipart Media Types。
大多数 multipart 媒体类型(包括定义解析所有 multipart 类型基础规则的
multipart/mixed)没有命名的部分。
这些媒体类型的数据被建模为数组,每个部分对应一个按序的项。
要使用 prefixEncoding 和/或 itemEncoding 字段,必须存在 itemSchema
或数组形式的 schema。
这些字段类似于 JSON Schema 的 prefixItems 和 items 关键字,其中
prefixEncoding(若存在)提供一个 Encoding Object 数组,每个 Encoding Object 应用于数据数组中相同位置的值,而
itemEncoding 将其单个 Encoding Object 应用于数组中剩余的所有项。
与 prefixItems 一样,如果实例数组比 prefixEncoding 数组短,这并非错误;额外的 Encoding Objects
SHALL 被忽略。
itemEncoding 字段也可与 itemSchema 一起使用以支持流式 multipart 内容。
prefixEncoding 字段可与任何 multipart 内容一起使用以强制固定的部分顺序。
这包括 multipart/form-data,对于此类情形,Encoding Object 的 headers 字段 MUST 用于提供 Content-Disposition 与部分名称,因为没有属性名可自动提供名称。
本规范的早期版本建议在非 multipart/form-data 的 multipart 媒体类型中使用每部分的
Content-Disposition: form-data 头的 name 参数 来规避
encoding 字段的限制。
实现 MAY 选择支持该变通方法,但由于该用法并不常见,非 form-data 类型的
multipart 媒体类型的实现很可能不会支持它。
有关表单相关与 multipart 媒体类型示例,请参见 Encoding Object。
请注意,由于此示例以 YAML 编写,Example Object 的 value 字段可以格式化为 YAML,因为 YAML 可轻松转换为 JSON,从而避免将
JSON 嵌入为字符串。
application/json:
schema:
$ref: '#/components/schemas/Pet'
examples:
cat:
summary: An example of a cat
value:
name: Fluffy
petType: Cat
color: White
gender: male
breed: Persian
dog:
summary: An example of a dog with a cat's name
value:
name: Puma
petType: Dog
color: Black
gender: Female
breed: Mixed
frog:
$ref: '#/components/examples/frog-example'
另外,由于所有 JSON 都是有效的 YAML,示例值也可以在 YAML 文档中使用 JSON 语法:
application/json:
schema:
$ref: '#/components/schemas/Pet'
examples:
cat:
summary: An example of a cat
value: {
"name": "Fluffy",
"petType": "Cat",
"color": "White",
"gender": "male",
"breed": "Persian"
}
dog:
summary: An example of a dog with a cat's name
value: {
"name": "Puma",
"petType": "Dog",
"color": "Black",
"gender": "Female",
"breed": "Mixed"
}
frog:
$ref: '#/components/examples/frog-example'
对于任何其序列项为 JSON 值的 顺序媒体类型,无需对每个值进行转换。
JSON 文本序列([RFC7464] 的
application/json-seq 以及 [RFC8091]
的 +json-seq 结构后缀)、JSON
Lines(application/jsonl)和 NDJSON(application/x-ndjson)都属于此类。注意
JSON Lines 与 NDJSON 的媒体类型尚未在 IANA 注册,但被广泛使用。
下面示例展示了用于流式日志条目和响应查询时返回固定长度集合的 Media Type Objects,展示了 schema 与
itemSchema 之间的关系以及何时使用它们,尽管在两种情况下 examples 字段相同。
components:
schemas:
LogEntry:
type: object
properties:
timestamp:
type: string
format: date-time
level:
type: integer
minimum: 0
message:
type: string
Log:
type: array
items:
$ref: "#/components/schemas/LogEntry"
maxItems: 100
examples:
LogJSONSeq:
summary: Log entries in application/json-seq
# JSON Text Sequences require an unprintable character
# that cannot be escaped in a YAML string, and therefore
# must be placed in an external document shown below
externalValue: examples/log.json-seq
LogJSONPerLine:
summary: Log entries in application/jsonl or application/x-ndjson
description: JSONL and NDJSON are identical for this example
# Note that the value must be written as a string with newlines,
# as JSONL and NDJSON are not valid YAML
value: |
{"timestamp": "1985-04-12T23:20:50.52Z", "level": 1, "message": "Hi!"}
{"timestamp": "1985-04-12T23:20:51.37Z", "level": 1, "message": "Bye!"}
responses:
LogStream:
description: |
A stream of JSON-format log messages that can be read
for as long as the application is running, and is available
in any of the sequential JSON media types.
content:
application/json-seq:
itemSchema:
$ref: "#/components/schemas/LogEntry"
examples:
JSON-SEQ:
$ref: "#/components/examples/LogJSONSeq"
application/jsonl:
itemSchema:
$ref: "#/components/schemas/LogEntry"
examples:
JSONL:
$ref: "#/components/examples/LogJSONPerLine"
application/x-ndjson:
itemSchema:
$ref: "#/components/schemas/LogEntry"
examples:
NDJSON:
$ref: "#/components/examples/LogJSONPerLine"
LogExcerpt:
description: |
A response consisting of no more than 100 log records,
generally as a result of a query of the historical log,
available in any of the sequential JSON media types.
content:
application/json-seq:
schema:
$ref: "#/components/schemas/Log"
examples:
JSON-SEQ:
$ref: "#/components/examples/LogJSONSeq"
application/jsonl:
schema:
$ref: "#/components/schemas/Log"
examples:
JSONL:
$ref: "#/components/examples/LogJSONPerLine"
application/x-ndjson:
schema:
$ref: "#/components/schemas/Log"
examples:
NDJSON:
$ref: "#/components/examples/LogJSONPerLine"
我们的 application/json-seq 示例必须放在外部文档中,因为它同时使用换行符和不可打印的记录分隔符(0x1E),该字符无法在
YAML 块文本中转义:
0x1E{
"timestamp": "1985-04-12T23:20:50.52Z",
"level": 1,
"message": "Hi!"
}
0x1E{
"timestamp": "1985-04-12T23:20:51.37Z",
"level": 1,
"message": "Bye!"
}
在此示例中,假设在 Special Considerations for
Server-Sent Events 节中提供的通用事件 schema 可通过 #/components/schemas/Event 访问:
description: A request body to add a stream of typed data.
required: true
content:
text/event-stream:
itemSchema:
$ref: "#/components/schemas/Event"
required: [event]
oneOf:
- properties:
event:
const: addString
- properties:
event:
const: addInt64
data:
$comment: |
Since the `data` field is a string,
we need a format to signal that it
should be handled as a 64-bit integer.
format: int64
- properties:
event:
const: addJson
data:
$comment: |
These content fields indicate
that the string value should
be parsed and validated as a
JSON document (since JSON is not
a binary format, `contentEncoding`
is not needed)
contentMediaType: application/json
contentSchema:
type: object
required: [foo]
properties:
foo:
type: integer
下面的 text/event-stream 文档是上述示例的一个有效请求体示例:
event: addString
data: This data is formatted
data: across two lines
retry: 5
event: addInt64
data: 1234.5678
unknownField: this is ignored
: This is a comment
event: addJSON
data: {"foo": 42}
为更清楚地展示该流如何处理,下面是等效的 JSON Lines 文档,显示数值与 JSON 数据如何作为字符串处理,以及未知字段与注释如何被忽略且不会传入 schema 验证:
{"event": "addString", "data": "This data is formatted\nacross two lines", "retry": 5}
{"event": "addInt64", "data": "1234.5678"}
{"event": "addJSON", "data": "{\"foo\": 42}"}
与 OpenAPI 2.0 相比,OAS 3.x 中的 file 输入/输出内容使用与任何其他 schema 类型相同的语义进行描述。
与 OAS 3.0 不同,OAS 3.1 中 format 关键字对 schema 的内容编码不再产生影响。取而代之的是使用 JSON Schema 的
contentEncoding 与 contentMediaType 关键字。有关如何使用这些关键字建模各种场景以及如何从先前的
format 用法迁移,请参见 Working With Binary Data。
示例:
以二进制(octet-stream)传输的内容 MAY 省略 schema:
# a PNG image as a binary file:
content:
image/png: {}
# an arbitrary binary file:
content:
application/octet-stream: {}
# arbitrary JSON without constraints beyond being syntactically valid:
content:
application/json: {}
这些示例适用于文件上传的输入有效载荷或作为响应的有效载荷。
用于在 POST 操作中提交文件的 requestBody 示例可能如下所示:
requestBody:
content:
application/octet-stream: {}
此外,可指定特定的媒体类型 MAY:
# multiple, specific media types may be specified:
requestBody:
content:
# a binary file of type png or jpeg
image/jpeg: {}
image/png: {}
要上传多个文件,必须使用 multipart 媒体类型,如 Example: Multipart Form with Multiple
Files 所示。
应用于单个值的单个编码定义,Encoding Objects 与值之间的映射由 Media Type Object 决定,详见 Encoding Usage and Restrictions。
有关将各种类型的值转换为字符串表示的讨论,请参阅 Appendix B。
有关表单媒体类型的百分号编码问题的详细检查,请参阅 Appendix E。
这些字段 MAY 可与下节所定义的 RFC6570 风格序列化字段一并使用或单独使用。
| 字段名 | 类型 | 描述 |
|---|---|---|
| contentType | string |
用于编码特定属性的 Content-Type。值为以逗号分隔的列表,每一项要么是具体的媒体类型(例如
image/png),要么是通配的媒体类型(例如 image/*)。默认值依赖于下表所示的类型。
|
| headers | Map[string, Header
Object | Reference Object] |
允许以头部形式提供附加信息的映射。
Content-Type 在此处单独描述并且在本节中 SHALL 被忽略。若媒体类型不是
multipart,则此字段 SHALL 被忽略。
|
| encoding | Map[string, Encoding Object] |
以与 Media Type Object 的 encoding
字段相同的方式应用嵌套的 Encoding Objects。 |
| prefixEncoding | [Encoding Object] | 以与 Media Type Object 的 prefixEncoding
字段相同的方式应用嵌套的 Encoding Objects。 |
| itemEncoding | Encoding Object | 以与 Media Type Object 的 itemEncoding
字段相同的方式应用嵌套的 Encoding Objects。 |
该对象 MAY 可通过 Specification Extensions 进行扩展。
contentType 的默认值如下,其中 n/a 在 contentEncoding 列中表示
contentEncoding 的存在或值与该情况无关。
本表基于 Encoding Object 所应用的值,参见 Encoding Usage and
Restrictions。
注意在 Encoding By Name 情况下,对于类型为 "array"
的属性,这一值是数组项;对于其它类型则是整个值。因此本表中 array 行仅适用于在按名称编码时位于顶层数组内部的数组值。
type |
contentEncoding |
默认 contentType |
|---|---|---|
| absent | n/a | application/octet-stream |
string |
present | application/octet-stream |
string |
absent | text/plain |
number, integer, or boolean |
n/a | text/plain |
object |
n/a | application/json |
array |
n/a | application/json |
如何处理 null 类型的 type 值取决于 null 值的序列化方式。
若 null 值被完全省略,则 contentType 无关紧要。
有关数据类型转换选项的讨论,请参阅 Appendix B。
| 字段名 | 类型 | 描述 |
|---|---|---|
| style | string |
描述特定属性值将如何根据其类型进行序列化。关于 Parameter Object 中 style 字段的详细信息请参阅相应部分。其行为与
query 参数采用相同的取值,包括默认值 "form"(该默认仅在由于显式指定了
explode 或 allowReserved 而未使用 contentType
时适用)。注意用于查询字符串的初始 ? 在 application/x-www-form-urlencoded
消息体中不使用,若使用 RFC6570 实现则 MUST 将其移除(若手动构造字符串则不要添加)。若媒体类型不是
application/x-www-form-urlencoded 或
multipart/form-data,则此字段 SHALL
被忽略。若显式定义了该值,则隐式或显式的 contentType
SHALL 被忽略。
|
| explode | boolean |
当为真时,类型为 array 或 object
的属性会为数组的每个值或映射的每个键值对生成独立的参数。对于其他类型的属性,或当 style 为 "deepObject"
时,该字段无效。若 style 为 "form",默认值为 true;其它样式默认值为
false。若媒体类型不是 application/x-www-form-urlencoded 或
multipart/form-data,此字段 SHALL
被忽略。若显式定义了该值,则隐式或显式的 contentType
SHALL 被忽略。
|
| allowReserved | boolean |
当为真时,参数值按 [RFC6570] 所定义的保留扩展进行序列化(参见 Section
3.2.3),这允许 RFC3986 的保留字符集以及百分号编码三元组保持不变,同时对所有其他不允许的字符进行百分号编码(包括百分号
%,若其不属于百分号编码三元组)。应用程序仍需对目标媒体类型不允许的保留字符进行百分号编码;详见 URL Percent-Encoding。默认值为
false。若媒体类型不是 application/x-www-form-urlencoded 或
multipart/form-data,此字段 SHALL
被忽略。若显式定义了该值,则隐式或显式的 contentType
SHALL 被忽略。
|
当对 multipart/form-data 使用 RFC6570 风格序列化时,MUST NOT 应用 URI
百分号编码,且 allowReserved 的值无影响。
另见 Appendix C: Using RFC6570
Implementations 以获取额外指导。
注意:至少存在 style、explode 或 allowReserved 中的任一显式值,相当于在
Parameter Objects 中使用 schema 且 in: "query"。
若这三者都缺失,则等同于使用 content,但媒体类型由 contentType 指定,而非通过 Media Type Object
指定。
需要编码的嵌套格式(最显著的是嵌套的 multipart/mixed)可以通过本对象的
encoding、prefixEncoding 和/或 itemEncoding 字段来支持。
实现 MUST 支持一级嵌套,并且 MAY 支持更多级别的嵌套。
要使用 [WHATWG-URL] 的表单 URL 编码规则处理内容,请在 Media Type Object 中使用
application/x-www-form-urlencoded 媒体类型。
这种配置意味着在任何复杂对象序列化为字符串表示之后,内容 MUST 按照该媒体类型的 [WHATWG-URL]
规则进行百分号编码。
有关表单媒体类型的百分号编码问题的详细检查,请参见 Appendix E。
当不存在 encoding 字段时,序列化策略基于 Encoding Object 的默认值:
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: string
format: uuid
address:
type: object
properties: {}
在此示例中,考虑一个 id 为 f81d4fae-7dec-11d0-a765-00a0c91e6bf6 且美国式地址(含 ZIP+4)如下:
{
"streetAddress": "123 Example Dr.",
"city": "Somewhere",
"state": "CA",
"zip": "99999+1234"
}
假设采用最紧凑的 JSON 表示(去除不必要的空白),我们期望看到如下请求体,其中空格字符被替换为 +,并且
+、"、:、,、{ 与 }
分别被百分号编码为 %2B、%22、%3A、%2C、%7B 与
%7D:
id=f81d4fae-7dec-11d0-a765-00a0c91e6bf6&address=%7B%22streetAddress%22%3A%22123+Example+Dr.%22%2C%22city%22%3A%22Somewhere%22%2C%22state%22%3A%22CA%22%2C%22zip%22%3A%2299999%2B1234%22%7D
注意根据 Encoding Object 的默认行为,id 关键字被视为 text/plain 并按原样序列化。
若将其视为 application/json,则序列化值将是包含引号的 JSON 字符串,而引号会被百分号编码为 %22。
下面示例展示将 id 参数(不含 address)作为 application/json 而不是
text/plain 序列化,然后按 [WHATWG-URL] 的
form-urlencoded 规则编码:
id=%22f81d4fae-7dec-11d0-a765-00a0c91e6bf6%22
注意 application/x-www-form-urlencoded 是文本格式,任何二进制数据都需要进行 base64 编码:
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
name:
type: string
icon:
# The default content type with `contentEncoding` present
# is `application/octet-stream`, so we need to set the correct
# image media type(s) in the Encoding Object.
type: string
contentEncoding: base64url
encoding:
icon:
contentType: image/png, image/jpeg
假设 name 为 example,且 icon 为一个实心红色的 2x2 像素 PNG,则会产生如下请求体:
name=example&icon=iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAABGdBTUEAALGPC_xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAAqADAAQAAAABAAAAAgAAAADO0J6QAAAAEElEQVQIHWP8zwACTGCSAQANHQEDqtPptQAAAABJRU5ErkJggg%3D%3D
注意即使使用“URL safe”的 contentEncoding: base64url,末尾的 = 填充字符仍需进行百分号编码。
一些 base64 解码实现可能根据 [RFC4648] 第 3.2 节
能够在没有填充的情况下处理字符串,但这并不保证,因此保留填充并依赖百分号解码通常更具互操作性。
关于将 schema 属性与各部分相关联的指导,请参阅 Encoding Usage and Restrictions。
注意一般情况下 multipart 媒体类型对可用头部有显著限制(参见 [RFC2046]
第 5.1 节)以及对 multi-part/form-data 的特殊限制(参见 [RFC7578] 第 4.8 节)。
当为 contentType 提供多个值时,解析仍然直接,因为文档中包含了该部分的实际 Content-Type。
对于编码和序列化,实施应 MUST 提供机制让应用程序指明意图使用的媒体类型。 实现 MAY 选择提供媒体类型嗅探([SNIFF])作为替代,但由于该过程固有的安全风险,该方法 MUST NOT 成为默认行为。
对 multipart 字段使用 contentEncoding 等同于指定一个 Encoding
Object,其 headers 字段包含一个要求使用 contentEncoding 值的
Content-Transfer-Encoding 的 schema。
若对一个 multipart 字段同时使用了 contentEncoding,且该字段的 Encoding Object 的 headers
中包含了一个不允许来自 contentEncoding 的值的 Content-Transfer-Encoding
schema,则序列化和解析的结果为未定义。
注意,如 Working with Binary Data 所述,若 Encoding Object 的
contentType(无论是显式设置还是通过默认规则隐式确定)与 Schema Object 中的 contentMediaType
不一致,则应忽略 contentMediaType。
因此,并且由于 Encoding Object 的 contentType 默认规则未考虑 Schema Object 的
contentMediaType,在 Encoding Object 中使用 contentMediaType NOT RECOMMENDED。
另请注意对于 multipart/form-data,Content-Transfer-Encoding 已被弃用(参见 [RFC7578] 第 4.7 节),因为
HTTP 已支持二进制数据。
有关表单媒体类型的百分号编码问题的详细检查,请参阅 Appendix E。
当不使用 encoding 字段时,编码由 Encoding Object 的默认值决定:
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
# default content type for a string without `contentEncoding`
# is `text/plain`
id:
type: string
format: uuid
# default content type for a schema without `type`
# is `application/octet-stream`
profileImage: {}
# for arrays, the `encoding` field applies the Encoding Object
# to each item individually and determines the default content type
# based on the type in the `items` subschema, which in this example
# is an object, so the default content type for each item is
# `application/json`
addresses:
type: array
items:
$ref: '#/components/schemas/Address'
使用 encoding,我们可以为二进制数据设置更具体的类型,或为复杂值设置非 JSON 格式。
我们也可以为每个部分描述其头部:
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
# No Encoding Object, so use default `text/plain`
id:
type: string
format: uuid
# Encoding Object overrides the default `application/json` content type
# for each item in the array with `application/xml; charset=utf-8`
addresses:
description: addresses in XML format
type: array
items:
$ref: '#/components/schemas/Address'
# Encoding Object accepts only PNG or JPEG, and also describes
# a custom header for just this part in the multipart format
profileImage: {}
encoding:
addresses:
contentType: application/xml; charset=utf-8
profileImage:
contentType: image/png, image/jpeg
headers:
X-Rate-Limit-Limit:
description: The number of allowed requests in the current period
schema:
type: integer
根据 [RFC7578] 第 4.3
节,单个表单字段的多个文件通过为每个文件的部分使用相同的名称(在本例中为 file)上传:
requestBody:
content:
multipart/form-data:
schema:
properties:
# The property name `file` will be used for all files.
file:
type: array
items: {}
如 Encoding Object 的 contentType 字段文档
中所示,items 的空 schema 表示媒体类型为 application/octet-stream。
一个由 JSON 元数据文档随后跟随该元数据所描述的图像组成的 multipart/mixed 有载荷示例:
multipart/mixed:
schema:
type: array
prefixItems:
- # default content type for objects
# is `application/json`
type: object
properties:
author:
type: string
created:
type: string
format: datetime
copyright:
type: string
license:
type: string
- # default content type for a schema without `type`
# is `application/octet-stream`, which we need
# to override.
{}
prefixEncoding:
- # Encoding Object defaults are correct for JSON
{}
- contentType: image/*
如 [RFC2557]
所述,一组构成网页的资源可以在 multipart/related 有载荷中发送,通过为每个页面定义 Content-Location
头来保留从 text/html 文档到从属资源(脚本、样式表、图像等)的链接。
第一部分被用作根资源(除非使用 RFC2557 建议避免且在本示例中被禁止的 Content-ID),因此我们使用 prefixItems
与 prefixEncoding 来定义其必须是 HTML 资源,然后允许若干种不同类型的资源以任意顺序跟随。
为避免对其 URI 值进行百分号编码,Content-Location 头使用 content: {text/plain: {...}}
定义;详见 Appendix D。
components:
headers:
RFC2557NoContentId:
description: Use Content-Location instead of Content-ID
schema: false
RFC2557ContentLocation:
required: true
content:
text/plain:
schema:
$comment: Use a full URI (not a relative reference)
type: string
format: uri
requestBodies:
RFC2557:
content:
multipart/related; type=text/html:
schema:
prefixItems:
- type: string
items:
anyOf:
- type: string
- $comment: To allow binary, this must always pass
prefixEncoding:
- contentType: text/html
headers:
Content-ID:
$ref: '#/components/headers/RFC2557NoContentId'
Content-Location:
$ref: '#/components/headers/RFC2557ContentLocation'
itemEncoding:
contentType: text/css,text/javascript,image/*
headers:
Content-ID:
$ref: '#/components/headers/RFC2557NoContentId'
Content-Location:
$ref: '#/components/headers/RFC2557ContentLocation'
本例假设一个设备拍摄大量图片并将其流式传输给调用方。与前例不同,我们在此使用
itemSchema,因为期望每张图片在到达时(或少量批次)被处理,而缓冲整个流将占用过多内存。
multipart/mixed:
itemSchema:
$comment: A single data image from the device
itemEncoding:
contentType: image/jpg
对于 multipart/byteranges(参见 [RFC9110] 第 14.6 节),需要包含
Content-Range 头:
关于为何使用 content: {text/plain: {...}} 来描述头值的解释,请参见 Appendix D。
multipart/byteranges:
itemSchema:
$comment: A single range of bytes from a video
itemEncoding:
contentType: video/mp4
headers:
Content-Range:
required: true
content:
text/plain:
schema:
# The `pattern` regular expression that would
# be included in practice is omitted for simplicity
type: string
此示例定义了一个两部分的 multipart/mixed,其中第一部分是一个 JSON 数组,第二部分是一个嵌套的
multipart/mixed 文档。嵌套部分为 XML、纯文本和 PNG 图像。
multipart/mixed:
schema:
type: array
prefixItems:
- type: array
- type: array
prefixItems:
- type: object
- type: string
- {}
prefixEncoding:
- {} # Accept the default application/json
- contentType: multipart/mixed
prefixEncoding:
- contentType: application/xml
- {} # Accept the default text/plain
- contentType: image/png
用于描述某个操作预期的响应的容器。 该容器将 HTTP 响应代码映射到预期的响应。
文档不一定需要覆盖所有可能的 HTTP 响应代码,因为某些响应代码可能事先未知。 但文档应当覆盖成功操作的响应以及任何已知的错误。
default MAY 可用作 Responses Object 中未单独覆盖的所有 HTTP 代码的默认 Response
Object。
Responses Object MUST 至少包含一个响应代码;如果只提供了一个响应代码,则该代码 SHOULD 为成功操作调用的响应。
| 字段名 | 类型 | 描述 |
|---|---|---|
| default | Response Object | Reference Object | 对未为特定 HTTP 响应代码声明的其它响应的文档。使用此字段来覆盖未声明的响应。 |
| 字段模式 | 类型 | 描述 |
|---|---|---|
| HTTP 状态码 | Response Object | Reference Object | 任意 HTTP 状态码 可用作属性名,但每个代码只能有一个属性,用以描述该 HTTP 状态码的预期响应。为兼容
JSON 与 YAML,此字段 MUST 用引号包围(例如,“200”)。要定义响应码范围,该字段 MAY 使用大写通配符字符 X,例如 2XX 表示所有 200 到 299
的响应代码。仅允许以下范围定义:1XX、2XX、3XX、4XX 和
5XX。若使用显式代码定义了某响应,则该显式定义优先于相应的范围定义。
|
该对象 MAY 可通过 规范扩展 进行扩展。
HTTP 状态码用于指示已执行操作的状态。 应当从 IANA Status Code Registry 中注册的可用状态码中选择状态码,尽量遵循该注册表。
一个用于成功操作的 200 响应,以及用于其它情况的默认响应(表示错误):
'200':
description: a pet to be returned
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
default:
description: Unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorModel'
描述 API 操作返回的单个响应,包括基于该响应的设计时静态 links 到其它操作。
| 字段名 | 类型 | 描述 |
|---|---|---|
| summary | string |
对该响应含义的简要概述。 |
| description | string |
对响应的描述。可以使用 [CommonMark] 语法来进行富文本表示(MAY)。 |
| headers | Map[string, Header
Object | Reference Object] |
将头名称映射到其定义。[RFC9110] 第 5.1 节 指出头名称不区分大小写。如果响应头以名称
"Content-Type" 定义,则应被忽略。
|
| content | Map[string, Media
Type Object | Reference Object] |
包含潜在响应负载描述的映射。键为媒体类型或 媒体类型范围,值描述该媒体类型。对于匹配多个键的响应,只有最具体的键适用(例如
"text/plain" 覆盖 "text/*")。
|
| links | Map[string, Link
Object | Reference Object] |
一个可从响应中跟随的操作链接映射。映射的键是链接的短名称,遵循 Component Objects 名称的命名约束。 |
该对象 MAY 可通过 规范扩展 进行扩展。
返回复杂类型数组的响应:
description: A complex object array response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/VeryComplexType'
返回字符串类型的响应:
description: A simple string response
content:
text/plain:
schema:
type: string
带头部的纯文本响应:
description: A simple string response
content:
text/plain:
schema:
type: string
example: 'whoa!'
headers:
X-Rate-Limit-Limit:
description: The number of allowed requests in the current period
schema:
type: integer
X-Rate-Limit-Remaining:
description: The number of remaining requests in the current period
schema:
type: integer
X-Rate-Limit-Reset:
description: The number of seconds left in the current period
schema:
type: integer
无返回值的响应:
description: object created
与父操作相关的可能的带外回调映射。 映射中的每个值都是一个 Path Item Object,用于描述 API 提供者可能发起的一组请求以及预期的响应。 用于标识 Path Item Object 的键是一个在运行时求值的表达式,用来标识回调操作要使用的 URL。
若要描述来自 API 提供者的入站请求(独立于另一次 API 调用),请使用 webhooks 字段。
| 字段模式 | 类型 | 描述 |
|---|---|---|
| {expression} | Path Item Object | 用于定义回调请求和预期响应的 Path Item Object。可参见一个 完整示例。 |
该对象 MAY 可通过 规范扩展 进行扩展。
用于标识 Path Item Object 的键是一个 运行时表达式,该表达式可以在运行时 HTTP 请求/响应的上下文中求值,以识别用于回调请求的 URL。例如,一个简单的示例可能是
$request.body#/url。
使用 运行时表达式 可以访问完整的 HTTP 消息,这包括访问 JSON Pointer [RFC6901] 可引用的任何部分。
例如,给定如下 HTTP 请求:
POST /subscribe/myevent?queryUrl=https://clientdomain.com/stillrunning HTTP/1.1
Host: example.org
Content-Type: application/json
Content-Length: 188
{
"failedUrl": "https://clientdomain.com/failed",
"successUrls": [
"https://clientdomain.com/fast",
"https://clientdomain.com/medium",
"https://clientdomain.com/slow"
]
}
结果为:
201 Created
Location: https://example.org/subscription/1
下面的示例展示了在假设回调操作具有名为 eventType 的路径参数和名为 queryUrl 的查询参数时,各表达式如何求值。
| 表达式 | 值 |
|---|---|
| $url | https://example.org/subscribe/myevent?queryUrl=https://clientdomain.com/stillrunning |
| $method | POST |
| $request.path.eventType | myevent |
| $request.query.queryUrl | https://clientdomain.com/stillrunning |
| $request.header.content-type | application/json |
| $request.body#/failedUrl | https://clientdomain.com/failed |
| $request.body#/successUrls/1 | https://clientdomain.com/medium |
| $response.header.Location | https://example.org/subscription/1 |
下面的示例使用用户提供的查询字符串参数 queryUrl 来定义回调 URL。这类似于 webhook,但不同之处在于回调仅在最初发送了 queryUrl 的请求之后才发生。
myCallback:
'{$request.query.queryUrl}':
post:
requestBody:
description: Callback payload
content:
application/json:
schema:
$ref: '#/components/schemas/SomePayload'
responses:
'200':
description: callback successfully processed
下面的示例展示了一个回调,其中服务器是硬编码的,但查询字符串参数由请求体中的 id 和 email 属性填充。
transactionCallback:
'http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}':
post:
requestBody:
description: Callback payload
content:
application/json:
schema:
$ref: '#/components/schemas/SomePayload'
responses:
'200':
description: callback successfully processed
将内部或外部示例值与基本的 summary 和 description 元数据分组的对象。
这些示例可以展示适用于 schema 验证的数据,或按包含的 Media Type Object、Parameter Object 或 Header Object 要求的序列化数据。
该对象通常用于名为 examples(复数)的字段,并且是可通过 Reference Object
引用的替代方案,弥补了旧的不可引用的单数 example 字段的不足。
在 Working With Examples 一节中对该对象的各字段与示例类型有更详细的说明。
| 字段名 | 类型 | 描述 |
|---|---|---|
| summary | string |
示例的简短描述。 |
| description | string |
示例的长描述。可以使用 [CommonMark] 语法来进行富文本表示(MAY)。 |
| dataValue | Any | 一个数据结构示例,该示例 MUST 符合相关的 Schema
Object 的要求。如果存在此字段,则 value MUST 缺失。 |
| serializedValue | string |
值的序列化形式示例,包含在 Validating Examples 中描述的编码与转义。如果存在
dataValue,则此字段 SHOULD 包含该数据的序列化结果。否则,它 SHOULD 为某个数据值的有效序列化,该数据值本身按 dataValue 的描述 MUST 有效。若序列化格式为 JSON,则不应使用此字段(SHOULD
NOT),因为数据形式更易于处理。如果此字段存在,则 value 与 externalValue MUST 缺失。
|
| externalValue | string |
一个 URI,标识位于单独文档中的序列化示例,允许表达不能以 Unicode 字符串容易或可读地表示的值。如果存在 dataValue,则该字段
SHOULD 标识给定数据的某种序列化形式。否则,该值 SHOULD
为某个数据值的有效序列化,而该数据值本身应当按 dataValue 的描述 MUST
有效。若此字段存在,则 serializedValue 与 value MUST 缺失。另见解析 相对引用 的规则。
|
| value | Any | 嵌入的字面示例。value 与 externalValue 互斥。对于无法自然以 JSON 或 YAML
表示的媒体类型示例,请使用字符串值包含示例并在必要时进行转义。对非 JSON 序列化目标已弃用:请改用 dataValue 和/或 serializedValue,它们具有无歧义的语法和语义。
|
该对象 MAY 可通过 规范扩展 进行扩展。
在所有情况下,示例值 SHOULD 与其关联值的 schema 兼容。工具实现 MAY 选择自动验证兼容性,并在不兼容时拒绝示例值。有关“兼容”的确切含义,请参见 Validating Examples 一节中对本对象每个字段的定义。
Example Objects 可用于 Parameter Objects、Header
Objects 和 Media Type Objects。
在这三类对象中,均通过 examples(复数)字段来完成。但也有其它提供示例的方式:在 Parameter、Header 或 Media Type 对象中互斥的单数
example 字段,以及在出现在三个对象的 schema 字段中的 Schema
Object 中的两个关键字(弃用的单数 example 与当前的复数 examples,后者接受示例数组)。
下文中我们将单数的简写 example 字段(在 Parameter、Header 或 Media Type 对象中,其行为等同于只有 value
字段的单一 Example Object)称为“简写 example”字段。每种字段都有稍微不同的考虑因素。
value 与简写 example 字段旨在具有与 serializedValue(或
externalValue)相同的语义,但在 JSON(或 JSON 兼容的 YAML)表示与最终序列化形式无差异时提供更方便的语法。当将此语法用于
application/json 或任何 +json 媒体类型时,这些字段实际上等同于
dataValue,因为序列化是平凡的,因此使用它们是安全的。
对于仅包含单个字符串的数据,且序列化目标如 text/plain 保证字符串以不需进一步转义的方式序列化时,这些字段也安全可用。
对于其它序列化目标,“自然地用 JSON 或 YAML 表示”的歧义性,以及先前参数样式示例表中的错误,导致这些字段在非 JSON 目标上的支持与用法存在不一致。因此,在实践中对于非 JSON
目标,value 与简写 example 字段的行为通常由实现定义;OAD 作者 SHOULD 使用其它字段以确保互操作性。
牢记上一节中的注意事项,以及当仅涉及一个 Example Object 时可用简写 example 代替 value
的事实,使用下列指南决定应使用哪一字段。
若要展示一个将如何被 Schema Object 验证的示例:
examples 数组(来自 JSON Schema draft
2020-12)。
example。dataValue 字段。
value 字段。
若要展示用于构建 HTTP/1.1 消息的序列化示例:
serializedValue 字段。
value 的字符串形式。externalValue。serializedValue 与 externalValue 两个字段都 MUST
展示数据的序列化形式。对于 Media Type Objects,这是一份合适媒体类型的文档,并应用任何 Encoding Object 的效果。对于使用
schema 与 style(而不是 Media Type Object)的 Parameter 与 Header Objects,请参见
Style Examples,了解何为序列化值。
若满足下列任一条件,则序列化可以在 serializedValue 中表示为有效的 Unicode 字符串:
charset 参数,并且该参数指示任何 Unicode 编码(UTF-8、UTF-16 等)或上述编码的有效子集(例如 US-ASCII)。
charset 覆盖。
application/json(默认 UTF-8)和
application/xml; charset=utf-8 的 multipart/mixed。
在所有这些情况下,将 OAD 的字符集(假定为 JSON 的互操作字符集 UTF-8)先转换为 Unicode 代码点,再转换为实际序列化字符集的过程是可定义的。
对于 externalValue,若未显式声明字符集且格式或媒体类型规范也未确定字符集,实施者 SHOULD 假设为
UTF-8。
工具实现 MAY 选择自动验证兼容性,并在不兼容时拒绝示例值。对于以 schema 就绪数据形式存在的示例,验证是直接且明确的。
对于序列化的示例,某些格式允许相同数据的多种有效表示形式(包括在 附录 B 中提到的场景)。在某些情况下,解析序列化示例并验证所得数据可以消除歧义,但在少数情况下解析本身也存在歧义。因此,OAD 作者应注意对某些序列化示例的验证在性质上属于尽力而为的特性。
在编写 YAML 时,dataValue 可以使用 JSON 语法(如 noRating 示例所示),但并非必须。虽然此示例对于 JSON
展示了 dataValue 与 serializedValue 的行为(在 withRating
示例中),但在大多数情况下只需要数据形式即可。
content:
application/json:
schema:
type: object
required:
- author
- title
properties:
author:
type: string
title:
type: string
rating:
type: number
minimum: 1
maximum: 5
multipleOf: 0.5
examples:
noRating:
summary: A not-yet-rated work
dataValue:
author: A. Writer
title: The Newest Book
withRating:
summary: A work with an average rating of 4.5 stars
dataValue:
author: A. Writer
title: An Older Book
rating: 4.5
serializedValue: |
{
"author": "A. Writer",
"title": "An Older Book",
"rating": 4.5
}
完整二进制数据使用 externalValue 展示:
content:
image/png:
schema: {}
examples:
Red:
externalValue: ./examples/2-by-2-red-pixels.png
由于布尔值序列化无统一标准(参见 附录 B),本示例使用
dataValue 与 serializedValue 来展示该参数的布尔序列化方式:
name: flag
in: query
required: true
schema:
type: boolean
examples:
"true":
dataValue: true
serializedValue: flag=true
"false":
dataValue: false
serializedValue: flag=false
Link Object 表示针对响应可能存在的设计时链接。 链接的存在并不保证调用方能够成功调用它,而是提供了响应与其它操作之间已知的关系与遍历机制。
与 动态 链接(即在响应负载中 提供 的链接)不同,OAS 的链接机制不要求在运行时响应中包含链接信息。
用于计算链接并提供执行指令的是一种用于访问操作中值并在调用链接操作时将其用作参数的 runtime expression。
| Field Name | Type | Description |
|---|---|---|
| operationRef | string |
指向 OAS 操作的 URI 引用。该字段与 operationId 字段互斥,且 MUST
指向一个 Operation Object。相对的 operationRef 值
MAY 用于在 OpenAPI 描述中定位已有的 Operation
Object。
|
| operationId | string |
一个 已存在、可解析的 OAS 操作的名称,该操作以唯一的 operationId 定义。此字段与
operationRef 字段互斥。
|
| parameters | Map[string, Any | {expression}] |
表示要传递给由 operationId 指定或通过 operationRef
标识的操作的参数的映射。键是要使用的参数名称(可选择地带位置限定,例如用于路径中的 id 参数可以写作
path.id),而值可以是常量或在运行时求值并传递给被链接操作的表达式。
|
| requestBody | Any | {expression} | 调用目标操作时用作请求体的字面值或 {expression}。 |
| description | string |
该链接的描述。可使用 [CommonMark] 语法进行富文本表示(MAY)。 |
| server | Server Object | 目标操作要使用的 server 对象。 |
该对象 MAY 通过 Specification Extensions 扩展。
被链接的操作 MUST 通过 operationRef 或 operationId 之一来标识。
被标识或引用的操作 MUST 是唯一的;在使用 operationId 的情况下,它 MUST 在 OpenAPI 描述(OAD)范围内可解析。
由于名称冲突的可能性,对于多文档的 OAD 更推荐使用 operationRef 语法。
但因为操作的使用取决于其在 Paths Object 中的 URL 路径模板,对于在 OAD 中被多次引用的任何 Path Item Object,这些操作可能无法唯一解析。
在此类不明确的情况下,结果行为为实现定义,并且 MAY 导致错误。
注意无法向 parameters 提供与运行时表达式语法相匹配的常量值。
参数名称可能存在歧义,例如 name: "id", in: "path" 与 name: "path.id", in: "query";这 NOT RECOMMENDED,其行为为实现定义。不过实现 SHOULD 优先采用限定的解释(将
path.id 视为路径参数),因为名称总可以通过限定来消歧(例如对查询参数使用 query.path.id)。
从请求操作计算链接的示例,其中使用 $request.path.id 来将请求路径参数传递给被链接的操作。
paths:
/users/{id}:
parameters:
- name: id
in: path
required: true
description: the user identifier, as userId
schema:
type: string
get:
responses:
'200':
description: the user being returned
content:
application/json:
schema:
type: object
properties:
uuid: # the unique user id
type: string
format: uuid
links:
address:
# the target link operationId
operationId: getUserAddress
parameters:
# get the `id` field from the request path parameter named "id"
userid: $request.path.id
# the path item of the linked operation
/users/{userid}/address:
parameters:
- name: userid
in: path
required: true
description: the user identifier, as userId
schema:
type: string
# linked operation
get:
operationId: getUserAddress
responses:
'200':
description: the user's address
当运行时表达式求值失败时,不会向目标操作传递该参数值。
可以使用响应体中的值来驱动被链接的操作。
links:
address:
operationId: getUserAddressByUUID
parameters:
# get the `uuid` field from the `uuid` field in the response body
userUuid: $response.body#/uuid
客户端可酌情跟随所有链接。 仅凭关系的存在并不能保证权限或能够成功调用该链接。
由于 operationId 在 Operation Object 中是可选字段,因此引用在某些情况下
MAY 通过 URI 引用与 operationRef 一起使用来代替。
注意以下两个示例都通过 Paths Object 可以标识操作,以确保该操作的路径模板是无歧义的。
一个相对 URI 引用的 operationRef:
links:
UserRepositories:
# returns array of '#/components/schemas/repository'
operationRef: '#/paths/~12.0~1repositories~1%7Busername%7D/get'
parameters:
username: $response.body#/username
一个非相对 URI 的 operationRef:
links:
UserRepositories:
# returns array of '#/components/schemas/repository'
operationRef: https://na2.gigantic-server.com/#/paths/~12.0~1repositories~1%7Busername%7D/get
parameters:
username: $response.body#/username
注意在使用 operationRef 时,在 URI 片段中使用 JSON Pointer 时需要对斜线进行转义(使用 ~1),并且需要将
{ 与 } 分别 URL 编码为 %7B 与 %7D。
上述示例中未转义、经百分号解码后的路径模板为 /2.0/repositories/{username}。
Runtime expressions 允许基于在实际 API 调用的 HTTP 消息中才可用的信息定义值。 该机制由 Link Objects 与 Callback Objects 使用。
运行时表达式由下列 [ABNF] 语法定义:
expression = "$url" / "$method" / "$statusCode" / "$request." source / "$response." source
source = header-reference / query-reference / path-reference / body-reference
header-reference = "header." token
query-reference = "query." name
path-reference = "path." name
body-reference = "body" ["#" json-pointer ]
json-pointer = *( "/" reference-token )
reference-token = *( unescaped / escaped )
unescaped = %x00-2E / %x30-7D / %x7F-10FFFF
; %x2F ('/') and %x7E ('~') are excluded from 'unescaped'
escaped = "~" ( "0" / "1" )
; representing '~' and '/', respectively
name = *char
token = 1*tchar
tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "."
/ "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
这里的 json-pointer 来源于 [RFC6901],
char 来源于 [RFC8259]
的相关部分,
而 token 来源于 [RFC9110] 的相关部分。
其中 name 标识符区分大小写,而 token 则不区分大小写。
下表给出了运行时表达式的示例及其在值中的使用示例:
| Source Location | example expression | notes |
|---|---|---|
| HTTP Method | $method |
$method 的允许值为 HTTP 操作所允许的那些方法。 |
| Requested media type | $request.header.accept |
|
| Request parameter | $request.path.id |
请求参数 MUST 在父操作的
parameters 部分中声明,否则无法被求值。此规则也适用于请求头。
|
| Request body property | $request.body#/user/uuid |
在接受有效载荷的操作中,可以引用 requestBody 的部分或整个请求体。 |
| Request URL | $url |
|
| Response value | $response.body#/status |
在返回有效载荷的操作中,可以引用响应体的部分或整个响应体。 |
| Response header | $response.header.Server |
仅可用单个头部值。 |
运行时表达式会保留被引用值的类型。
可以通过用花括号 {} 将表达式包围的方式将表达式嵌入到字符串值中。
描述用于 HTTP responses 以及用于 在
multipart 表示中的各部分 的单个 header;请参阅相关的 Response Object
与 Encoding Object 文档以了解哪些头可以被描述的限制。
Header Object 遵循 Parameter Object 的结构,包括基于是否存在 schema 或
content 来确定其序列化策略,但有如下更改:
name MUST NOT 指定,名称由对应的 headers 映射给出。in MUST NOT 指定,其隐含位置为 header。header(例如 style)。这意味着 allowEmptyValue MUST NOT 被使用,且若使用 style,则 MUST 限定为
"simple"。
这些字段 MAY 与 content 或 schema 一起使用。
example 与 examples 字段互斥;有关验证要求的指导,请参见 Working with Examples。
| Field Name | Type | Description |
|---|---|---|
| description | string |
该 header 的简要描述。可以包含使用示例。可使用 [CommonMark] 语法来进行富文本表示(MAY)。 |
| required | boolean |
确定该 header 是否为必需。默认值为 false。 |
| deprecated | boolean |
指定该 header 已被弃用并且 SHOULD 逐步停止使用。默认值为 false。
|
| example | Any | header 可能值的示例;参见 Working With Examples。 |
| examples | Map[ string, Example Object | Reference Object] |
header 可能值的示例集合;参见 Working With Examples。 |
该对象 MAY 通过 Specification Extensions 扩展。
对于简单场景,schema 与 style 可以描述 header 的结构与语法。
在使用 schema 序列化 header 时,MUST NOT 应用 URI 百分号编码;若使用会自动应用编码的
RFC6570 实现,则在使用前 MUST 撤销该编码。
实现 MUST 原样传递 header 值,而不要尝试自动为 header 值添加引用,因为不同 header
的引用规则差异过大;有关引用与转义的指导,请参见 Appendix D。
| Field Name | Type | Description |
|---|---|---|
| style | string |
描述 header 值将如何序列化。默认值(也是 header 的唯一合法值)为 "simple"。 |
| explode | boolean |
当为 true 时,类型为 array 或 object 的 header 值将产生一个单一
header,其值为数组项或映射键值对的以逗号分隔的列表,参见 Style
Examples。对于其他数据类型此字段无效。默认值为 false。 |
| schema | Schema Object | 定义用于该 header 的类型的 schema。 |
另见 Appendix C: Using RFC6570-Based Serialization 以获取更多指导。
对于更复杂的情形,content 字段可定义 header 的媒体类型和 schema,并提供其使用示例。
| Field Name | Type | Description |
|---|---|---|
| content | Map[string, Media Type Object | Reference Object] |
包含 header 表示形式的映射。键是媒体类型,值描述该媒体类型。该映射 MUST 仅包含一项条目。 |
[RFC9264]
定义了 application/linkset 与 application/linkset+json 媒体类型。
前者恰好是 HTTP Link header 值的格式,只是允许为可读性添加额外空白;后者则是此类头的等价 JSON 表示形式。
要使用这两种媒体类型中的任意一种,Media Type Object 中的 schema MUST 描述这些链接在 application/linkset+json 格式中将如何结构化。
如果 Media Type Object 的父键为 application/linkset+json,则序列化是平凡的,但该格式不能用于 HTTP 的
Link 头。
如果 Media Type Object 的父键为 application/linkset,则序列化 MUST 为
schema 所建模链接在 application/linkset 格式中的等价表示。
如果在 Header Object 的 content 字段中使用 application/linkset Media Type Object(或在
in: "header" 的 Parameter Object 中使用),则该序列化 MUST 与 RFC9264 所述的
HTTP 字段语法兼容(参见 RFC9264 的相关节)。
下面示例展示了相同的数据模型如何既作为消息内容的 JSON 格式用于集合分页 linkset,也可在 HTTP Link 头中使用:
components:
schemas:
SimpleLinkContext:
type: array
items:
type: object
required:
- href
properties:
href:
type: string
format: uri-reference
CollectionLinks:
type: object
required:
- linkset
properties:
linkset:
type: array
items:
type: object
required: [first, prev, next, last]
properties:
anchor:
type: string
format: uri
additionalProperties:
$ref: '#/components/schemas/SimpleLinkContext'
responses:
CollectionWithLinks:
content:
application/json:
schema:
type: array
headers:
Link:
required: true
content:
application/linkset:
schema:
$ref: '#/components/schemas/CollectionLinks'
StandaloneJsonLinkset:
content:
application/linkset+json:
schema:
$ref: '#/components/mediaTypes/CollectionLinks'
一个简单的 integer 类型 header:
X-Rate-Limit-Limit:
description: The number of allowed requests in the current period
schema:
type: integer
要求存在强 ETag 头(值以 " 开始,而不是 W/):
ETag:
required: true
schema:
type: string
# Note that quotation marks are part of the
# ETag value, unlike many other headers that
# use a quoted string purely for managing
# reserved characters.
pattern: ^"
example: '"xyzzy"'
为单个标签添加由 Operation Object 使用的元数据。对于 Operation Object 实例中定义的每个标签,并非强制要求都存在一个 Tag Object。
| 字段名 | 类型 | 描述 |
|---|---|---|
| name | string |
REQUIRED。标签的名称。在 Operation 的 tags
数组中使用此值。 |
| summary | string |
标签的简短摘要,用于显示目的。 |
| description | string |
标签的描述。可以使用 [CommonMark] 语法来进行富文本表示,MAY 使用。 |
| externalDocs | External Documentation Object | 该标签的额外外部文档。 |
| parent | string |
该标签所嵌套的父标签的 name。被引用的标签 MUST 必须存在于 API
描述中,且父子标签之间不得出现循环引用(MUST NOT)。 |
| kind | string |
用于机器可读的字符串,用以对标签进行分类。可以使用任意字符串;常见用途有用于导航的 nav、用于可见徽章的
badge、用于不同用户群体的 API 的 audience 等。可参见 常用值注册表。
|
此对象 MAY 使用 Specification Extensions 进行扩展。
tags:
- name: account-updates
summary: Account Updates
description: Account update operations
kind: nav
- name: partner
summary: Partner
description: Operations available to the partners network
parent: external
kind: audience
- name: external
summary: External
description: Operations available to external consumers
kind: audience
一个用于在 OpenAPI 描述中引用其他组件的简单对象,支持内部和外部引用。
$ref 字符串值包含一个 URI [RFC3986],用于标识被引用的值。
关于解析 相对引用 的规则,请参见相关说明。
| 字段名 | 类型 | 描述 |
|---|---|---|
| $ref | string |
REQUIRED。引用标识符。此值 MUST 必须为 URI 形式。 |
| summary | string |
简短摘要,默认情况下 SHOULD 覆盖被引用组件的摘要。如果被引用的对象类型不允许 summary
字段,则此字段无效。 |
| description | string |
描述,默认情况下 SHOULD 覆盖被引用组件的描述。可以使用 [CommonMark] 语法进行富文本表示(MAY)。如果被引用的对象类型不允许 description 字段,则此字段无效。 |
此对象不能扩展额外属性,任何被添加的属性 SHALL 被忽略。
注意:对于包含 $ref 关键字的 Schema Objects,与 Reference Objects 在额外属性方面存在差异。
$ref: '#/components/schemas/Pet'
$ref: Pet.yaml
$ref: definitions.yaml#/Pet
Schema Object 允许定义输入和输出的数据类型。这些类型可以是对象,也可以是原语或数组。该对象是 JSON Schema Specification
Draft 2020-12 的超集。空模式(允许任何实例通过验证)MAY 可由布尔值 true
表示,而不允许任何实例通过验证的模式 MAY 可由布尔值 false 表示。
关于关键字的更多信息,请参见 JSON Schema Core 与 JSON Schema Validation。
除非另有说明,关键字定义遵循 JSON Schema 的定义且不添加额外语义;这包括诸如 $schema、$id、$ref 和
$dynamicRef 等关键字为 URI 而非 URL 的情况。若 JSON Schema 指出某些行为由应用决定(例如注释),OAS 也将语义定义延迟给使用该 OpenAPI
文档的应用。
OpenAPI Schema Object 的 方言 被定义为需要包含 OAS 基础词汇,另外还包含 JSON Schema Specification Draft 2020-12 中指定的词汇表(参见 通用 meta-schema)。
此版本规范的 OpenAPI Schema Object 方言由 URI https://spec.openapis.org/oas/3.1/dialect/base 标识(即
“OAS 方言模式 id”)。
以下关键字来自 JSON Schema 规范,但在 OAS 中其定义有所扩展:
除了组成 OAS 方言的 JSON Schema 关键字外,Schema Object 还支持来自其他词汇表的关键字或任意属性。
JSON Schema 实现 MAY 选择将由 OpenAPI 规范基础词汇定义的关键字视为 未知关键字,因为其在
OAS 方言中以 $vocabulary
值为 false 的方式被包含。
OAS 基础词汇由以下关键字组成:
| 字段名 | 类型 | 描述 |
|---|---|---|
| discriminator | Discriminator Object | discriminator 提供了一个“提示”,指出有效载荷应满足哪一组模式之一。更多细节见 组合与继承。 |
| xml | XML Object | 添加额外元数据以描述该模式的 XML 表现形式。 |
| externalDocs | External Documentation Object | 该模式的额外外部文档。 |
| example | Any | 用于包含该模式实例示例的自由字段。若示例无法自然地用 JSON 或 YAML
表示,可使用字符串值并在必要时进行转义。 已弃用:字段 example 已被 JSON Schema
的 examples 关键字取代。建议不要使用 example,未来版本规范可能移除该字段。 |
此对象 MAY 使用 Specification Extensions
进行扩展,尽管如上所述,在该对象内额外属性 MAY 可以省略 x- 前缀。
OAS 中的数据类型基于 JSON Schema Validation Specification Draft 2020-12 定义的类型: “null”、 “boolean”、 “object”、 “array”、 “number”、 “string” 或 “integer”。模型使用 Schema Object 定义,该对象是 JSON Schema Specification Draft 2020-12 的超集。
JSON Schema 的关键字与 format 值作用于可能是六种 JSON 数据类型之一的 JSON
“实例”:“null”、“boolean”、“object”、“array”、“number” 或 “string”,且某些关键字和格式仅适用于特定类型。例如,关键字
pattern 和格式 date-time 仅适用于字符串,并将其它五种类型的任何实例视为“自动通过”。这意味着 JSON Schema
的关键字和格式并不隐式地要求某个期望类型。若要显式约束类型,请使用 type 关键字。
注意,type 关键字允许使用 "integer" 作为值以便于使用,但关键字和格式的适用性并不将整数视为与其它数字不同的 JSON 类型,因为
JSON
本身并不做此区分。由于不存在独立的 JSON 整数类型,JSON Schema 以数学方式定义整数。这意味着 1 与 1.0
在语义上被视为等价,二者都被认为是整数。
如 JSON
Schema Validation 规范 所定义,数据类型可以有一个可选的修饰关键字:format。如该规范所述,默认情况下
format 被视为非验证注释;是否验证 format 取决于具体实现。
OpenAPI Initiative 还托管了一个 Format Registry,用于记录由 OAS 用户和其它规范定义的格式。对任何注册格式的支持完全是 可选 的,对一个注册格式的支持并不意味着对其他格式的支持。
未伴随 format 关键字的类型遵循 JSON Schema 中的类型定义。若工具不识别某个特定 format,则可 MAY 回退仅按 type 进行处理,仿佛未指定 format。针对 JSON
Schema 验证,每个格式应指定其适用的 JSON 数据类型集合。在此注册表中,这些类型在“JSON Data Type”列中列出。
OAS 定义的格式如下:
format |
JSON 数据类型 | 备注 |
|---|---|---|
int32 |
number | 有符号 32 位 |
int64 |
number | 有符号 64 位(即 long) |
float |
number | |
double |
number | |
password |
string | 提示应对该值进行隐藏处理。 |
如在 数据类型 一节所述,type: number 与 type: integer
在数据模型中都被视为数字。
API 数据有几种形式:
format 和
contentType)以及可能的额外信息(例如类层次结构)传达的附加信息。这些超出本规范范围的内容 MAY
基于规范元素(如 Discriminator Object)或关于 数据建模技术 的指引来实现。
JSON 序列化的数据几乎等同于数据形式,因为 JSON
Schema 的数据模型 与 JSON 表示几乎一致。序列化的 UTF-8 JSON 字符串
{"when": "1985-04-12T23:20:50.52"} 表示一个具有单个数据字段的对象,该字段名为 when,其字符串值为
1985-04-12T23:20:50.52。
具体的应用形式超出本规范范围,但可通过下面的模式示例说明我们的 JSON 实例:
type: object
properties:
when:
type: string
format: date-time
一些应用可能会将该字符串在任意编程语言中保持为字符串,而其他应用可能会注意到 format 并将其作为 Python 的
datetime.datetime 实例,或 Java 的
java.time.ZonedDateTime。本规范仅要求数据根据模式有效,且诸如 format 之类作为注释的关键字按 JSON
Schema 规范可用。
非 JSON 的序列化形式可能与其对应的数据形式有很大不同,且可能需要多个步骤才能解析。
延续我们的 “when” 示例,如果我们将对象序列化为 application/x-www-form-urlencoded,它将以 ASCII
字符串的形式出现:when=1985-04-12T23%3A20%3A50.52。该示例仍然易于使用,因为都是字符串数据,且与 JSON 的唯一区别是 URI
百分号编码和分隔语法(使用 = 替代 JSON 标点和引号)。
然而,许多非 JSON 的文本格式可能很复杂,必须检查相应的模式以将文本正确解析为可供模式使用的数据结构。将数据序列化为此类格式需要检查经过模式验证的数据,或执行相同的模式检查。
在检查模式时,给定一个起始模式,实施者 MUST 检查该模式以及通过仅跟随 $ref 和
allOf 关键字可到达的所有模式。这些模式保证适用于任何实例。在搜索模式以查找 type 时,如果 type
关键字的值是类型列表,并且序列化值可以成功解析为列表中多个类型之一,且没有其它可发现的 type 关键字来消除歧义,则行为由实现定义。未包含
type 的 Schema Objects MUST 被视为允许所有类型,无论其它关键字如何存在(例如
maximum 适用于数字,但并不要求实例必须为数字)。
实现 MAY 检查子模式或其它关键字(如 oneOf 或 $dynamicRef)
的可能引用目标,但 MUST NOT 试图解决歧义。例如,如果实现选择检查 anyOf,下列模式:
anyOf:
- type: number
minimum: 0
- type: number
maximum: 100
明确地指出了数字类型,但下列模式:
anyOf:
- type: number
- maximum: 100
则不明确,因为第二个子模式允许所有类型。
鉴于这些对模式搜索的有限要求,能够访问已验证数据的序列化器 MUST 在可能的情况下检查实际数据;不处理运行时数据(例如代码生成器)或无法访问已验证数据的实现 MUST 回退到模式检查。
还应记住,在 JSON Schema 中适用于特定类型的关键字(例如 pattern 适用于字符串,minimum
适用于数字)并不要求或暗示数据实际上会是该类型。
作为这些过程的示例,给定以下 OpenAPI 组件:
components:
requestBodies:
Form:
content:
application/x-www-form-urlencoded:
schema:
$ref: "#/components/schemas/FormData"
encoding:
extra:
contentType: application/xml
schemas:
FormData:
type: object
properties:
code:
allOf:
- type: [string, number]
pattern: "1"
minimum: 0
- type: string
pattern: "2"
count:
type: integer
extra:
type: object
以及下面这个要解析为数据形式的请求体:
code=1234&count=42&extra=%3Cinfo%3Eabc%3C/info%3E
我们必须首先在模式中搜索 properties 或其它定义属性的关键字,然后将每个属性的模式作为起点去搜索该属性的 type
关键字,过程如下(具体顺序由实现定义):
#/components/requestBodies/Form/content/application~1x-www-form-urlencoded/schema(起始模式,仅包含
$ref)
#/components/schemas/FormData(跟随 $ref,发现 properties)
#/components/schemas/FormData/properties/code(code 属性的起始模式)#/components/schemas/FormData/properties/code/allOf/0(跟随 allOf,发现
type: [string, number])
#/components/schemas/FormData/properties/code/allOf/1(跟随 allOf,发现
type: string)
#/components/schemas/FormData/properties/count(count 属性的起始模式,发现
type: integer)
#/components/schemas/FormData/properties/extra(extra 属性的起始模式,发现
type: object)
注意对 code 我们起初找到一个模糊的 type,但随后又找到了另一个 type
关键字,使两种可能性中只有一种有效。
通过这种检查,我们确定 code 是一个看起来像数字的字符串,而 count
需要在模式验证之前被解析为数字。此外,extra 字符串实际上是一个表示含有 info 属性的对象的 XML
序列化。这意味着该序列化的数据形式等价于下面的 JSON 对象:
{
"code": "1234",
"count": 42
"extra": {
"info": "abc"
}
}
序列化该对象还需要将属性与 Encoding Objects 关联,并可能需要检查以确定
contentType 字段的默认值。如果无法获取到已验证的数据,则模式检查过程与解析时相同。
在该示例中,code 和 count 都是原始类型,且未出现在 encoding
字段中,因此按纯文本序列化。然而,extra 字段是一个对象,默认会被序列化为 JSON,但 encoding 字段中对
extra 的条目告知要改为以 XML 形式序列化。
OAS 可描述 原始 或 编码 的二进制数据。
multipart/* 有效负载的一部分。
application/json 或
application/x-www-form-urlencoded(无论是作为消息体还是 URL 查询字符串的一部分)。
在下面展示如何为二进制数据使用 Schema Object 关键字的表中,我们以 image/png 作为示例二进制媒体类型。任何二进制媒体类型(包括
application/octet-stream)均可表示二进制内容。
| 关键字 | 原始 | 编码 | 备注 |
|---|---|---|---|
type |
省略 | string |
原始二进制位于 type 之外 |
contentMediaType |
image/png |
image/png |
若冗余可有时省略(见下文) |
contentEncoding |
省略 | base64 或 base64url |
其它编码也被 允许 |
注意:由 contentEncoding 指示的编码会增大数据大小以便表示为 7 位 ASCII 文本,这与 HTTP 的
Content-Encoding 头(标识消息体是否以及如何被压缩)无关,且该头在本节描述的所有内容序列化完成后应用。由于 HTTP
允许未编码的二进制消息体,因此没有标准的 HTTP 头用于指示整个消息体使用 base64 或类似编码。
使用 contentEncoding 为 base64url 可确保在查询字符串和类型为
application/x-www-form-urlencoded 的消息体中所需的 URL 编码不需对已编码的二进制数据再做额外编码。
若媒体类型已设置,则 contentMediaType 关键字是冗余的,具体场景包括:
contentType 字段中如果 Schema Object 将由非 OAS 感知的 JSON Schema 实现处理,即便冗余也可能有用以包含 contentMediaType。但若
contentMediaType 与相关的 Media Type Object 或 Encoding Object 冲突,则
contentMediaType SHALL 被忽略。
有关流式二进制有效负载的指导,请参见 完整内容 与 流式内容。
较少的 JSON Schema 实现直接支持处理二进制数据,因为这不是该规范的强制部分。
无法获得支持二进制实例的 JSON Schema 实现的 OAS 实现 MUST 按照 处理二进制数据 一节的要求检查并应用模式。当整个实例为二进制时,因相关关键字较少,处理较为直接。
然而,multipart 媒体类型可以混合二进制和文本数据,使实现对于模式评估有两种选择:
properties、prefixItems
等),以便拆分子模式并分别将它们应用到二进制和与 JSON 兼容的数据。下面的表展示了如何从 OAS 3.0 的二进制数据描述迁移(继续以 image/png 为示例二进制媒体类型):
| OAS < 3.1 | OAS >= 3.1 | 备注 |
|---|---|---|
type: stringformat: binary |
contentMediaType: image/png |
若冗余可省略,通常会导致一个空的 Schema Object |
type: stringformat: byte |
type: stringcontentMediaType: image/pngcontentEncoding: base64 |
注意可以使用 base64url 以避免将 base64 字符串重新编码为 URL 安全形式 |
JSON Schema Draft 2020-12 支持 收集注释,包括将未识别的关键字视为注释的处理(见
相关说明)。OAS
实现 MAY 使用这些注释(包括未被声明的 JSON Schema 词汇表识别的 扩展)作为进一步验证的基础。注意 JSON Schema Draft
2020-12 并不要求扩展使用 x- 前缀。
当使用默认的 format-annotation 词汇表时,format
关键字,以及 contentMediaType、contentEncoding
和 contentSchema 关键字对数据定义约束,但被视为注释而非直接验证。扩展验证是强制执行这些约束的一种方式,且这些约束 MAY 被这样执行。
readOnly 与 writeOnly 关键字是注释,因为 JSON Schema 无法知道它正在验证的数据将如何被使用。对这些关键字的验证
MAY 通过检查注释、读/写方向以及(若相关)字段的当前值来完成。JSON
Schema Validation Draft 2020-12 第 9.4 节 定义了这些关键字的期望行为,包括资源(称为“拥有权威”) MAY 忽略 readOnly 字段或将其视为错误。
同时为必需且只读的字段是一个示例,说明在 PUT 请求中忽略 readOnly: true 约束可能是有益的,特别是在值未被更改的情况下。这允许在 GET
时正确要求该字段,同时仍然在 PUT 时使用相同的表示与模式。即便只读字段不是必需的,移除它们对客户端来说也是繁重的,尤其当 JSON 数据复杂或深度嵌套时。
注意 readOnly 的行为与本规范的 3.0 版本存在差异。
OpenAPI 规范允许使用 JSON Schema 的 allOf 关键字来组合和扩展模型定义,从而实现模型组合。allOf
接受一组对象定义的数组,这些定义独立验证,但一起组成单个对象。
尽管组合提供了模型的可扩展性,但并不意味着模型之间存在继承层次结构。
JSON Schema 还提供 anyOf 和 oneOf 关键字,分别允许定义多个模式,其中至少一个或恰好一个必须有效。与
allOf 相同,这些模式也是独立验证的。这些关键字可用于描述多态,在该场景中单个字段可以接受多种类型的值。
OpenAPI 规范通过添加 discriminator 字段(其值为 Discriminator Object)扩展了 JSON Schema
对多态的支持。使用时,Discriminator Object 指示用于提示哪个 anyOf 或 oneOf
模式应验证模型结构的属性名称。判定属性 MAY 被定义为必需或可选,但若将其定义为可选,则 Discriminator Object MUST 包含 defaultMapping 字段,以指定在判定属性不存在时期望使用哪个
anyOf 或 oneOf 中的模式,或在 allOf 中引用当前模式的哪个模式。
定义继承实例的判定属性值有两种方式:
实现 SHOULD 支持使用 JSON Schema 的动态引用功能来定义通用或模板数据结构:
$dynamicAnchor 标识一组可能的模式(包括默认的占位模式),$dynamicRef 可解析到这些模式之一。$dynamicRef 按 JSON Schema 规范,从模式入口点到引用路径上遇到的第一个匹配 $dynamicAnchor
进行解析。示例包含在下方的 Schema Object 示例 部分,并且在 Learn OpenAPI 网站的 “动态引用” 页面上有更多信息。
Schema Object 的 enum 关键字不允许为各个值关联描述或其它信息。
实现 MAY 支持识别一种模式:将 oneOf 或 anyOf 中的每个子模式写为包含
const 关键字及诸如 title 或 description 等注释,从而作为带有附加信息的枚举类型。此模式在
JSON Schema 所要求行为之外的具体行为由实现定义。
xml 字段在将 JSON 定义转换为 XML 时允许额外定义。XML Object 包含有关可用选项的更多信息。
工具需要能够确定任一资源希望使用哪个方言或元模式进行处理:JSON Schema Core、JSON Schema Validation、OpenAPI Schema 方言或某个自定义元模式。
$schema 关键字 MAY 出现在作为 模式资源根
的任何 Schema Object 中,若存在则 MUST 用于确定处理该模式时应使用哪个方言。这允许使用不同于默认 Draft 2020-12
的其它 JSON Schema 草案的 Schema Object。工具 MUST 支持 OAS 方言模式 id,且 MAY 支持 $schema
的其他取值。
为了允许对包含在 OAS 文档中的所有 Schema Object 使用不同的默认 $schema 值,可在 OpenAPI
Object 中设置 jsonSchemaDialect。若未设置该默认值,则这些 Schema Object 必须使用 OAS 方言模式 id。资源根
Schema Object 中的 $schema 值始终覆盖任何默认值。
对于未设置 $schema 的独立 JSON Schema 文档,或对于不作为 完整文档 的 OpenAPI 描述文档中的 Schema Object,方言 SHOULD 假定为 OAS 方言。然而,为了最大互操作性,建议 OpenAPI 描述作者在此类文档中显式通过
$schema 设置方言。
type: string
format: email
type: object
required:
- name
properties:
name:
type: string
address:
$ref: '#/components/schemas/Address'
age:
type: integer
format: int32
minimum: 0
用于简单的字符串到字符串的映射:
type: object
additionalProperties:
type: string
用于字符串到模型的映射:
type: object
additionalProperties:
$ref: '#/components/schemas/ComplexModel'
oneOf:
- const: RGB
title: Red, Green, Blue
description: Specify colors with the red, green, and blue additive color model
- const: CMYK
title: Cyan, Magenta, Yellow, Black
description: Specify colors with the cyan, magenta, yellow, and black subtractive color model
type: object
properties:
id:
type: integer
format: int64
name:
type: string
required:
- name
examples:
- name: Puma
id: 1
components:
schemas:
ErrorModel:
type: object
required:
- message
- code
properties:
message:
type: string
code:
type: integer
minimum: 100
maximum: 600
ExtendedErrorModel:
allOf:
- $ref: '#/components/schemas/ErrorModel'
- type: object
required:
- rootCause
properties:
rootCause:
type: string
下面示例描述了一个 Pet 模型,该模型可表示猫或狗,区分依据为 petType 属性。每种宠物类型在基础 Pet
模型之外有额外属性。若实例缺少 petType 属性,或该属性值既不是 cat 也不是 dog,则该实例无效。
components:
schemas:
Pet:
type: object
properties:
name:
type: string
required:
- name
- petType
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
Cat:
description: A pet cat
type: object
properties:
petType:
const: 'cat'
huntingSkill:
type: string
description: The measured skill for hunting
enum:
- clueless
- lazy
- adventurous
- aggressive
required:
- huntingSkill
Dog:
description: A pet dog
type: object
properties:
petType:
const: 'dog'
packSize:
type: integer
format: int32
description: the size of the pack the dog is from
default: 0
minimum: 0
required:
- packSize
下面的示例在上一节示例的基础上,为 Pet 模式添加了一个 Discriminator
Object。注意 Discriminator Object 仅为 API 使用者提供提示,并不会改变模式的验证结果。
components:
schemas:
Pet:
type: object
discriminator:
propertyName: petType
mapping:
cat: '#/components/schemas/Cat'
dog: '#/components/schemas/Dog'
properties:
name:
type: string
required:
- name
- petType
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
Cat:
description: A pet cat
type: object
properties:
petType:
const: 'cat'
huntingSkill:
type: string
description: The measured skill for hunting
enum:
- clueless
- lazy
- adventurous
- aggressive
required:
- huntingSkill
Dog:
description: A pet dog
type: object
properties:
petType:
const: 'dog'
packSize:
type: integer
format: int32
description: the size of the pack the dog is from
default: 0
minimum: 0
required:
- petType
- packSize
也可以使用 allOf 描述多态模型。以下示例使用 allOf 和 Discriminator Object 来描述一个多态的 Pet 模型。
components:
schemas:
Pet:
type: object
discriminator:
propertyName: petType
properties:
name:
type: string
petType:
type: string
required:
- name
- petType
Cat: # "Cat" will be used as the discriminating value
description: A representation of a cat
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
properties:
huntingSkill:
type: string
description: The measured skill for hunting
enum:
- clueless
- lazy
- adventurous
- aggressive
required:
- huntingSkill
Dog: # "Dog" will be used as the discriminating value
description: A representation of a dog
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
properties:
packSize:
type: integer
format: int32
description: the size of the pack the dog is from
default: 0
minimum: 0
required:
- packSize
components:
schemas:
genericArrayComponent:
$id: fully_generic_array
type: array
items:
$dynamicRef: '#generic-array'
$defs:
allowAll:
$dynamicAnchor: generic-array
numberArray:
$id: array_of_numbers
$ref: fully_generic_array
$defs:
numbersOnly:
$dynamicAnchor: generic-array
type: number
stringArray:
$id: array_of_strings
$ref: fully_generic_array
$defs:
stringsOnly:
$dynamicAnchor: generic-array
type: string
objWithTypedArray:
$id: obj_with_typed_array
type: object
required:
- dataType
- data
properties:
dataType:
enum:
- string
- number
oneOf:
- properties:
dataType:
const: string
data:
$ref: array_of_strings
- properties:
dataType:
const: number
data:
$ref: array_of_numbers
当请求体或响应负载可能属于多种不同模式之一时,应使用 JSON Schema 的 anyOf 或 oneOf 关键字来描述可能的模式(见 组合与继承)。
多态模式 MAY 包含一个判别器(Discriminator Object),用于定义可作为提示的属性名称,该属性可指示在 anyOf
或 oneOf 中哪个模式,或在 allOf
中引用当前模式的哪个模式,预期用于验证模型结构。该提示可以用于帮助序列化、反序列化和验证。判别器对象通过隐式或显式地将命名属性的可能值与替代模式关联来实现此目的。
注意 discriminator MUST NOT 改变模式的验证结果。
| Field Name | Type | Description |
|---|---|---|
| propertyName | string |
REQUIRED。载荷中用于保存判别值的判定属性的名称。判定属性 MAY 被定义为必需或可选,但当定义为可选时,判别器对象 MUST 包含一个
defaultMapping 字段,该字段指定在判定属性不存在时代码期望用于验证模型结构的模式。
|
| mapping | Map[string, string] |
用于保存载荷值与模式名称或 URI 引用之间映射的对象。 |
| defaultMapping | string |
当载荷中未包含判定属性或判定属性包含没有显式或隐式映射的值时,预期用于验证模型结构的模式名称或模式的 URI 引用。 |
此对象 MAY 使用 Specification Extensions 进行扩展。
只有在使用复合关键字之一 oneOf、anyOf 或 allOf 时,判别器对象才是合法的。
在 oneOf 和 anyOf 的用例中,当这些关键字与 discriminator 并列时,所有可能的模式 MUST 被显式列出。
为避免冗余,判别器 MAY 被添加到父模式定义中,通过 allOf 构建在该父模式之上的所有模式都可以作为备选模式使用。
allOf 形式的 discriminator 仅对非验证用途有用;使用该形式的 discriminator
与父模式一起进行验证时,不会 搜索子模式或以任何方式在验证中使用它们。这是因为 discriminator 无法改变验证结果,并且没有标准的 JSON
Schema 关键字将父模式与子模式连接起来。
任何未在上述描述中的 oneOf、anyOf、allOf 与 discriminator
的配置的行为均未定义。
propertyName 指定的属性的值被用作在 Components Object
下关联模式的名称,除非该值存在对应的 mapping。mapping 条目将特定的属性值映射到不同的模式组件名称或由 URI
标识的模式。当使用隐式或显式的模式组件名称时,内联的 oneOf 或 anyOf 子模式不予考虑。若某个 mapping
值或 defaultMapping 值同时是有效的模式名称和有效的相对 URI 引用,则其行为由实现定义,但建议(RECOMMENDED)将其视为模式名称。为确保歧义值(例如 "foo")被所有实现视为相对 URI 引用,作者 MUST 在其前面加上路径段 "."(例如 "./foo")。
映射键 MUST 为字符串值,但工具链 MAY 将响应值转换为字符串以便比较。然而,此类转换的具体性质由实现定义。
当判定属性被定义为可选时,判别器对象 MUST 包含一个
defaultMapping 字段,指定在载荷中判定属性不存在或包含没有显式或隐式映射值时,预期用于验证模型结构的模式。这样即使缺少判定属性,模式仍能被正确验证。
可选判定属性的主要用途是允许在不破坏未提供判定属性的现有客户端的情况下向模式添加判别器。
当判定属性被定义为可选时,每个在子模式中定义了该判定属性值的子模式也应将该属性定义为必需,因为父模式不再强制执行此项。
defaultMapping 模式也应在判定属性存在但其值没有显式或隐式映射时,能用于验证模型结构。通常在 defaultMapping
模式中通过排除任何具有映射判定值的实例来表达,例如:
OtherPet:
type: object
properties:
petType:
not:
enum: ['cat', 'dog']
这可以防止 defaultMapping 模式验证包含已映射判定值的载荷,否则使用 oneOf 描述多态时会导致验证失败。
在这些示例中,假设所有模式都位于 OAD 的 入口文档;关于在被引用文档中处理
discriminator 的说明,请参见 解析隐式连接。
在 OAS 3.x 中,响应负载 MAY 被描述为恰好为任意数量类型之一:
MyResponseType:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Lizard'
这意味着有效载荷必须恰好匹配由 Cat、Dog 或 Lizard 描述的其中一个模式。对
oneOf 的反序列化可能代价较高,因为需要确定哪个模式匹配载荷并因此应在反序列化中使用。对于 anyOf
模式也存在相同问题。discriminator 可作为提示以提高选择匹配模式的效率。判别器对象不能改变 oneOf
的验证结果,它只能帮助提高反序列化效率并提供更好的错误消息。我们可以指定确切的字段来告诉我们哪个模式预期匹配该实例:
MyResponseType:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Lizard'
discriminator:
propertyName: petType
现在的预期是响应载荷中 petType 名称的属性 MUST 出现,其值将对应于在 OpenAPI
描述中定义的某个模式名称。例如,下面的响应载荷:
{
"id": 12345,
"petType": "Cat"
}
将表明预期匹配该载荷的模式是 Cat。
在判定属性的值不匹配模式名称或无法进行隐式映射的情况下,可以使用可选的 mapping 定义:
MyResponseType:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Lizard'
- $ref: https://gigantic-server.com/schemas/Monster/schema.json
discriminator:
propertyName: petType
mapping:
dog: '#/components/schemas/Dog'
monster: https://gigantic-server.com/schemas/Monster/schema.json
此处判别值 dog 将映射到模式 #/components/schemas/Dog,而不是默认的(隐式)值
#/components/schemas/dog。如果判别值既不匹配隐式也不匹配显式映射,则无法确定模式,验证 SHOULD
失败。
当与 anyOf 结构结合使用时,判别器可避免在多个模式可能满足单个载荷时对序列化/反序列化器造成歧义。
当判定属性被定义为可选时,判别器对象必须包含一个 defaultMapping 字段,指定在载荷中判定属性不存在时代码期望用于验证模型结构的
anyOf 或 oneOf 中的某个模式。这样即使缺少判定属性,模式仍能被正确验证。
例如:
MyResponseType:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Lizard'
- $ref: '#/components/schemas/OtherPet'
discriminator:
propertyName: petType
defaultMapping: OtherPet
OtherPet:
type: object
properties:
petType:
not:
enum: ['Cat', 'Dog', 'Lizard']
在此示例中,如果载荷中不存在 petType 属性,或 petType 的值不是 “Cat”、“Dog” 或 “Lizard”,则该载荷应针对
OtherPet 模式进行验证。
下面的示例展示了使用 allOf 的用法,从而避免在父模式中引用所有子模式:
components:
schemas:
Pet:
type: object
required:
- petType
properties:
petType:
type: string
discriminator:
propertyName: petType
mapping:
dog: Dog
Cat:
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
# all other properties specific to a `Cat`
properties:
name:
type: string
Dog:
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
# all other properties specific to a `Dog`
properties:
bark:
type: string
Lizard:
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
# all other properties specific to a `Lizard`
properties:
lovesRocks:
type: boolean
针对 Pet 模式验证时,像下面这样的载荷:
{
"petType": "Cat",
"name": "Misty"
}
将表明预期匹配 #/components/schemas/Cat。同样地,下面的载荷:
{
"petType": "dog",
"bark": "soft"
}
将映射到 #/components/schemas/Dog,因为 mapping 元素中的 dog 条目映射到了模式名
Dog(即 #/components/schemas/Dog)。
一个元数据对象,用于更细粒度地定义 XML 模型。当在 Schema Object 中使用 XML 时,如果没有提供 XML Object,则行为由 XML Object 的默认字段值决定。
| Field Name | Type | Description |
|---|---|---|
| nodeType | string |
取值为 element、attribute、text、cdata 或
none 之一,详见 XML 节点类型。当包含该 XML Object 的 Schema Object 中存在
$ref、$dynamicRef 或 type: "array" 时,默认值为
none,否则为 element。
|
| name | string |
设置与该模式对应的元素/属性名称,替换在 XML 节点名称 中说明的推断名称。当
nodeType 为 text、cdata 或 none 时,该字段
SHALL 被忽略。
|
| namespace | string |
命名空间定义的 IRI(参见 RFC3987)。该值 MUST 为非相对 IRI。 |
| prefix | string |
用于 name 的前缀。 |
| attribute | boolean |
声明该属性定义是否应转换为属性而不是元素。默认值为 false。如果存在 nodeType,则此字段 MUST NOT 出现。已弃用:请使用 nodeType: "attribute" 代替 attribute: true
|
| wrapped | boolean |
仅可用于数组定义。表示数组是否被包裹(例如
<books><book/><book/></books>)或未包裹(例如 <book/><book/>)。默认值为
false。该定义仅在与 type 为 "array"(位于 items
之外)同时定义时生效。如果存在 nodeType,此字段 MUST NOT
出现。已弃用:请使用 nodeType: "element" 代替
wrapped: true
|
注意,从对象数据生成 XML 文档时,节点的顺序是未定义的。若需控制节点顺序,请使用 prefixItems,详见 有序元素与文本。
关于将各种类型的值转换为字符串表示的讨论,请参见 附录 B。
此对象 MAY 使用 Specification Extensions 进行扩展。
每个 Schema Object 描述由 nodeType 字段指定的特定类型的 XML [DOM] 节点,其可能值如下。除特殊值 none 外,这些值在
DOM 规范中有对应的数字等价(括号中给出):
element (1):该模式表示一个元素并描述其内容attribute (2):该模式表示一个属性并描述其值text (3):该模式表示一个文本节点(解析字符数据)cdata (4):该模式表示一个 CDATA 节none:该模式不对应于 XML 文档中的任何节点,其子模式对应的节点直接包含在其父模式的节点下none 类型对需要比 XML 节点更多 Schema Objects 的 JSON Schema 构造(例如仅包含 $ref
的为便于重用而存在的模式)很有用。
为兼容历史,type: "array" 的模式默认 nodeType: "none",将每个数组项的节点放在父节点下。这也与 XML 节点名称 中定义的推断命名行为一致。
要生成包含列表的元素,请在 type: "array" 模式上显式设置
nodeType: "element"。在此情况下,建议对包裹元素或项元素之一设置显式名称,以避免它们具有相同的推断名称。请参见示例以了解预期行为。
如果某个 element 节点具有原始类型,则该模式还会为该 element 节点的内容生成一个由该元素内容的模式描述的隐式
text 节点,名称为属性名(或 name 字段)。
如果一个元素同时具有属性与内容,则需要显式的 text 节点。
注意,将两个 text 节点相邻放置对解析来说是歧义的,其结果行为由实现定义。
element 和 attribute 节点类型需要名称,该名称 MUST
按照如下方式从模式中推断,除非被 name 字段覆盖:
schemas
字段下的模式,组件名称为推断名称。schema
字段下的内联模式,无法推断名称,因此必须存在带有 name 字段的 XML Object。注意:在使用数组时,不会推断单数或复数形式,必须显式设置。
namespace 字段旨在匹配 XML 命名空间的语法(参见 XML
namespaces),但有几点注意事项:
XML 默认情况下没有等价于 null 的概念,为了与本规范 3.1.1 及更早版本兼容,序列化 null 值的行为由实现定义。
然而,实现 SHOULD 按如下方式处理 null 值:
xsi:nil="true" 属性的空元素。注意:对于属性,这意味着 null 值或缺失属性都会序列化为省略的属性。由于 Schema Object 验证的是内存表示,这允许处理 null
与必需属性的组合。然而,因为无法以不同方式将 null 表示为属性,建议(RECOMMENDED)将属性类型设为可选而非使用
null。
为确保正确的往返行为,在解析省略了属性的元素时,如果模式允许该值(例如 type: ["number", "null"]),实现 SHOULD 将对应属性设置为 null,否则应省略该属性(例如 type: "number")。
下面在每个模式后给出一个为该模式生成的示例 XML 表示。有关使用 attribute 或 wrapped 的示例,请参见 OpenAPI
Specification 3.1。
基本字符串属性没有 XML Object,使用 serializedValue(其余示例将使用 externalValue
以便在带语法高亮的情况下展示 XML 形式):
application/xml:
schema:
type: object
xml:
name: document
properties:
animals:
type: string
examples:
pets:
dataValue:
animals: dog, cat, hamster
serializedValue: |
<document>
<animals>dog, cat, hamster</animals>
</document>
基本字符串数组属性(默认 nodeType 为 none):
application/xml:
schema:
type: object
xml:
name: document
properties:
animals:
type: array
items:
type: string
examples:
pets:
dataValue:
animals:
- dog
- cat
- hamster
externalValue: ./examples/pets.xml
其中 ./examples/pets.xml 将为:
<document>
<animals>dog</animals>
<animals>cat</animals>
<animals>hamster</animals>
</document>
application/xml:
schema:
type: object
xml:
name: document
properties:
animals:
type: string
xml:
name: animal
examples:
pets:
dataValue:
animals:
- dog
- cat
- hamster
externalValue: ./examples/pets.xml
其中 ./examples/pets.xml 将为:
<document>
<animal>dog</animal>
<animal>cat</animal>
<animal>hamster</animal>
</document>
注意根 XML 元素的名称来自组件名称。
components:
schemas:
Person:
type: object
properties:
id:
type: integer
format: int32
xml:
nodeType: attribute
name:
type: string
xml:
namespace: https://example.com/schema/sample
prefix: sample
requestBodies:
Person:
content:
application/xml:
schema:
$ref: "#/components/schemas/Person"
examples:
Person:
dataValue:
id: 123
name: example
externalValue: ./examples/Person.xml
其中 ./examples/Person.xml 将为:
<Person id="123">
<sample:name xmlns:sample="https://example.com/schema/sample">example</sample:name>
</Person>
更改元素名称示例:
application/xml:
schema:
type: object
xml:
name: document
properties:
animals:
type: array
items:
type: string
xml:
name: animal
examples:
pets:
dataValue:
animals:
- dog
- cat
- hamster
externalValue: ./examples/pets.xml
其中 ./examples/pets.xml 将为:
<document>
<animal>dog</animal>
<animal>cat</animal>
<animal>hamster</animal>
</document>
对于 type: "array" 模式,其 name 字段无效,因为该对象的默认 nodeType 为
none:
application/xml:
schema:
type: object
xml:
name: document
properties:
animals:
type: array
xml:
name: aliens
items:
type: string
xml:
name: animal
examples:
pets:
dataValue:
animals:
- dog
- cat
- hamster
externalValue: ./examples/pets.xml
其中 ./examples/pets.xml 将为:
<document>
<animal>dog</animal>
<animal>cat</animal>
<animal>hamster</animal>
</document>
即使通过将 nodeType 显式设置为 element 创建了包裹元素,如果未显式定义名称,则包装元素和列表项元素将使用相同名称:
application/xml:
schema:
type: object
xml:
name: document
properties:
animals:
type: array
xml:
nodeType: element
items:
type: string
examples:
pets:
dataValue:
animals:
- dog
- cat
- hamster
externalValue: ./examples/pets.xml
其中 ./examples/pets.xml 将为:
<document>
<animals>
<animals>dog</animals>
<animals>cat</animals>
<animals>hamster</animals>
</animals>
</document>
为解决上述命名问题,可使用如下定义:
application/xml:
schema:
type: object
xml:
name: document
properties:
animals:
type: array
xml:
nodeType: element
items:
type: string
xml:
name: animal
examples:
pets:
dataValue:
animals:
- dog
- cat
- hamster
externalValue: ./examples/pets.xml
其中 ./examples/pets.xml 将为:
<document>
<animals>
<animal>dog</animal>
<animal>cat</animal>
<animal>hamster</animal>
</animals>
</document>
同时影响包裹元素和项元素名称的例子:
application/xml:
schema:
type: object
xml:
name: document
properties:
animals:
type: array
xml:
name: aliens
nodeType: element
items:
type: string
xml:
name: animal
examples:
pets:
dataValue:
animals:
- dog
- cat
- hamster
externalValue: ./examples/pets.xml
其中 ./examples/pets.xml 将为:
<document>
<aliens>
<animal>dog</animal>
<animal>cat</animal>
<animal>hamster</animal>
</aliens>
</document>
如果我们更改包装元素名称但不更改项元素名称:
application/xml:
schema:
type: object
xml:
name: document
properties:
animals:
type: array
xml:
name: aliens
nodeType: element
items:
type: string
examples:
pets:
dataValue:
animals:
- dog
- cat
- hamster
externalValue: ./examples/pets.xml
其中 ./examples/pets.xml 将为:
<document>
<aliens>
<aliens>dog</aliens>
<aliens>cat</aliens>
<aliens>hamster</aliens>
</aliens>
</document>
application/xml:
schema:
type: array
xml:
nodeType: element
name: animals
items:
xml:
name: animal
properties:
kind:
type: string
xml:
nodeType: attribute
name:
type: string
xml:
nodeType: text
examples:
pets:
dataValue:
- kind: Cat
name: Fluffy
- kind: Dog
name: Fido
其中 ./examples/pets.xml 将为:
<animals>
<animal kind="Cat">Fluffy</animals>
<animal kind="Dog">Fido</animals>
<animals>
在此示例中,仅包含 $ref 的 Schema Object 不会创建元素,因为其 nodeType 默认为
none。必须为 CDATA 节创建子模式,否则内容将被视为类型为 text 的隐式节点。
components:
schemas:
Documentation:
type: object
properties:
content:
type: string
contentMediaType: text/html
xml:
nodeType: cdata
responses:
content:
application/xml:
schema:
$ref: "#/components/schemas/Documentation"
examples:
docs:
dataValue:
content: <html><head><title>Awesome Docs</title></head><body></body><html>
externalValue: ./examples/docs.xml
其中 ./examples/docs.xml 将为:
<Documentation>
<![CDATA[<html><head><title>Awesome Docs</title></head><body></body><html>]]>
</Documentation>
或者,可以在使用点设置命名根元素并在组件处禁用根元素(注意在此示例中,相同的 dataValue 在两个位置使用,不同的序列化通过
externalValue 显示):
paths:
/docs:
get:
responses:
"200":
content:
application/xml:
schema:
xml:
nodeType: element
name: StoredDocument
$ref: "#/components/schemas/Documentation"
examples:
stored:
dataValue:
content: <html><head><title>Awesome Docs</title></head><body></body><html>
externalValue: ./examples/stored.xml
put:
requestBody:
required: true
content:
application/xml:
schema:
xml:
nodeType: element
name: UpdatedDocument
$ref: "#/components/schemas/Documentation"
examples:
updated:
dataValue:
content: <html><head><title>Awesome Docs</title></head><body></body><html>
externalValue: ./examples/updated.xml
responses:
"201": {}
components:
schemas:
Documentation:
xml:
nodeType: none
type: object
properties:
content:
type: string
contentMediaType: text/html
xml:
nodeType: cdata
其中 ./examples/stored.xml 将为:
<StoredDocument>
<![CDATA[<html><head><title>Awesome Docs</title></head><body></body><html>]]>
</StoredDocument>
而 ./examples/updated.xml 将为:
<UpdatedDocument>
<![CDATA[<html><head><title>Awesome Docs</title></head><body></body><html>]]>
</UpdatedDocument>
要控制元素的确切顺序,请使用 prefixItems 关键字。采用该方法时,需要使用 XML Object
显式设置元素名称,否则它们尽管在特定顺序中为不同元素,却都会继承父元素的名称。此外,需要在数组上显式设置
nodeType: "element",以获取包含序列的元素。
下面第一个有序示例展示了元素序列,以及推荐的元素 null 序列化方式:
application/xml:
schema:
xml:
nodeType: element
name: OneTwoThree
type: array
minLength: 3
maxLength: 3
prefixItems:
- xml:
name: One
type: string
- xml:
name: Two
type: object
required:
- unit
- value
properties:
unit:
type: string
xml:
nodeType: attribute
value:
type: number
xml:
nodeType: text
- xml:
name: Three
type:
- boolean
- "null"
examples:
OneTwoThree:
dataValue:
- Some text
- unit: cubits
value: 42
null
]
externalValue: ./examples/OneTwoThree.xml
其中 ./examples/OneTwoThree.xml 将为:
<OneTwoThree>
<One>Some text</One>
<Two unit="cubits">42</Two>
<Three xsi:nil="true" />
</OneTwoThree>
在下一个示例中,需要为元素设置 name,同时为文本节点设置 nodeType。
application/xml:
schema:
xml:
nodeType: element
name: Report
type: array
prefixItems:
- xml:
nodeType: text
type: string
- xml:
name: data
type: number
- xml:
nodeType: text
type: string
examples:
Report:
dataValue:
- Some preamble text.
- 42
- Some postamble text.
externalValue: ./examples/Report.xml
其中 ./examples/Report.xml 将为:
<Report>Some preamble text.<data>42</data>Some postamble text.</Report>
请记住,模式验证的是内存数据,而不是 XML 文档本身。此示例未为 "related" 定义属性,因为它展示了空对象和 null 的处理方式。
application/xml:
schema:
xml:
name: product
type: object
required:
- count
- description
- related
properties:
count:
type:
- number
- "null"
xml:
nodeType: attribute
rating:
type: string
xml:
nodeType: attribute
description:
type: string
related:
type:
- object
- "null"
examples:
productWithNulls:
dataValue:
count: null
description: Thing
related: null
externalValue: ./examples/productWithNulls.xml
productNoNulls:
dataValue:
count: 42
description: Thing
related: {}
externalValue: ./examples/productNoNulls.xml
其中 ./examples/productWithNulls.xml 将为:
<product>
<description>Thing</description>
<related xsi:nil="true" />
</product>
而 ./examples/productNoNulls.xml 将为:
<product count="42">
<description>Thing</description>
<related></related>
</product>
定义可被操作使用的安全方案。
支持的方案包括 HTTP 验证、API 密钥(作为头部、cookie 参数或查询参数)、双向 TLS(使用客户端证书)、OAuth2 的常见流程(隐式、密码、客户端凭证和授权代码),如 [RFC6749] 所定义;OAuth2 设备授权流程,如 [RFC8628] 所定义;以及 [OpenID-Connect-Core]。请注意,截至 2020 年,隐式流程已由 OAuth 2.0 Security Best Current Practice 建议弃用。对于大多数使用场景,推荐使用带 PKCE 的授权代码授权(Authorization Code Grant)流程。
| 字段名 | 类型 | 适用对象 | 描述 |
|---|---|---|---|
| type | string |
Any | REQUIRED。安全方案的类型。有效值为
"apiKey"、"http"、"mutualTLS"、"oauth2"、"openIdConnect"。
|
| description | string |
Any | 安全方案的描述。可以使用 [CommonMark] 语法进行富文本表示(MAY)。 |
| name | string |
apiKey |
REQUIRED。要使用的头部、查询或 cookie 参数的名称。 |
| in | string |
apiKey |
REQUIRED。API 密钥的位置。有效值为
"query"、"header" 或 "cookie"。
|
| scheme | string |
http |
REQUIRED。在 Authorization 头中使用的 HTTP 认证方案的名称,如 [RFC9110] 第 16.4.1 节 所定义。建议使用在 IANA Authentication Scheme registry 中注册的值。该值为不区分大小写,依据 [RFC9110] 第 11.1 节 的定义。 |
| bearerFormat | string |
http ("bearer") |
提示客户端了解承载令牌的格式。承载令牌通常由授权服务器生成,因此此信息主要用于文档说明。 |
| flows | OAuth Flows Object | oauth2 |
REQUIRED。包含对所支持流程类型的配置的对象。 |
| openIdConnectUrl | string |
openIdConnect |
REQUIRED。用于发现 [OpenID-Connect-Discovery] 提供者元数据的 Well-known URL。 |
| oauth2MetadataUrl | string |
oauth2 |
OAuth2 授权服务器元数据的 URL [RFC8414]。要求使用 TLS。 |
| deprecated | boolean |
Any | 声明该安全方案已被弃用。使用者 SHOULD 避免使用该声明的方案。默认值为 false。 |
此对象 MAY 使用 规范扩展 进行扩展。
type: http
scheme: basic
type: apiKey
name: api-key
in: header
type: http
scheme: bearer
bearerFormat: JWT
type: mutualTLS
description: Cert must be signed by example.com CA
type: oauth2
flows:
implicit:
authorizationUrl: https://example.com/api/oauth/dialog
scopes:
write:pets: modify pets in your account
read:pets: read your pets
允许配置所支持的 OAuth 流程。
| 字段名 | 类型 | 描述 |
|---|---|---|
| implicit | OAuth Flow Object | OAuth 隐式流程的配置 |
| password | OAuth Flow Object | OAuth 资源所有者密码(Resource Owner Password)流程的配置 |
| clientCredentials | OAuth Flow Object | OAuth 客户端凭证(Client Credentials)流程的配置。在 OpenAPI 2.0 中曾被称为 application。 |
| authorizationCode | OAuth Flow Object | OAuth 授权代码(Authorization Code)流程的配置。在 OpenAPI 2.0 中曾被称为 accessCode。 |
| deviceAuthorization | OAuth Flow Object | OAuth 设备授权(Device Authorization)流程的配置。 |
此对象 MAY 使用 规范扩展 进行扩展。
受支持的 OAuth 流的配置详情
| 字段名 | 类型 | 适用对象 | 描述 |
|---|---|---|---|
| authorizationUrl | string |
oauth2 ("implicit", "authorizationCode") |
REQUIRED。用于此流程的 authorization URL。该值 MUST 必须为 URL 形式。OAuth2 标准要求使用 TLS。 |
| deviceAuthorizationUrl | string |
oauth2 ("deviceAuthorization") |
REQUIRED。用于此流程的 device authorization URL。该值 MUST 必须为 URL 形式。OAuth2 标准要求使用 TLS。 |
| tokenUrl | string |
oauth2 ("password", "clientCredentials",
"authorizationCode", "deviceAuthorization")
|
REQUIRED。用于此流程的 token URL。该值 MUST 必须为 URL 形式。OAuth2 标准要求使用 TLS。 |
| refreshUrl | string |
oauth2 |
用于获取刷新令牌的 URL。该值 MUST 必须为 URL 形式。OAuth2 标准要求使用 TLS。 |
| scopes | Map[string, string] |
oauth2 |
REQUIRED。OAuth2 安全方案可用的 scopes。一个从 scope 名称到其简短描述的映射。该映射 MAY 为空。 |
此对象 MAY 使用 Specification Extensions 进行扩展。
type: oauth2
flows:
implicit:
authorizationUrl: https://example.com/api/oauth/dialog
scopes:
write:pets: 修改您账户中的宠物
read:pets: 读取您的宠物
authorizationCode:
authorizationUrl: https://example.com/api/oauth/dialog
tokenUrl: https://example.com/api/oauth/token
scopes:
write:pets: 修改您账户中的宠物
read:pets: 读取您的宠物
列出执行此操作所需的安全方案。
用于每个属性的名称 MUST 要么对应于在 Components
Object 下的 Security Schemes 中声明的安全方案,要么为 Security Scheme Object
的 URI。与 Components Object 下组件名称相同的属性名 MUST 被视为组件名称。为了引用与组件名冲突的单段相对 URI 引用(例如
foo 对应 #/components/securitySchemes/foo),请使用 . 路径段(例如
./foo)。
使用看起来像 URI 的安全方案组件名称 NOT RECOMMENDED,因为为兼容之前的 OAS 版本需要将组件名称匹配优先于 URI 解析,这一点可能违反直觉。另请参见 安全注意事项。
Security Requirement Object MAY 引用多个安全方案,在这种情况下,所有这些方案 MUST 都必须满足,才能使请求被授权。这支持需要通过多个查询参数或 HTTP 头传递安全信息的场景。
当在 OpenAPI Object 或 Operation Object 上定义
security 字段并包含多个 Security Requirement Objects 时,列表中的任意一项满足即可授权请求。这支持 API 允许多种独立安全方案的场景。
空的 Security Requirement Object({})表示支持匿名访问。
| 字段模式 | 类型 | 描述 |
|---|---|---|
| {name} | [string] |
每个名称或 URI MUST 对应上述描述的安全方案。如果安全方案类型为 "oauth2" 或
"openIdConnect",则其值为执行所需的 scope 名称列表;若授权不要求指定 scope,则该列表 MAY 为空。对于其它安全方案类型,数组 MAY
包含执行所需的角色名称,但这些角色名称不会在带内定义或交换。
|
另见 隐式连接解析示例(位于 附录 G:解析与解析指导),其中展示了在多文档 OpenAPI 描述中使用 Security Requirement Objects 的示例。
api_key: []
此示例使用 Security Scheme 的组件名称。
petstore_auth:
- write:pets
- read:pets
此示例使用 Security Scheme 的相对 URI 引用。
在 OpenAPI Object 或 Operation Object 中定义的可选 OAuth2 安全示例如下:
security:
- {}
- petstore_auth:
- write:pets
- read:pets
尽管 OpenAPI 规范试图涵盖大多数用例,但可以在某些点添加额外数据以扩展规范。
扩展属性以模式化字段实现,始终以 x- 为前缀。
| 字段模式 | 类型 | 描述 |
|---|---|---|
| ^x- | Any | 允许对 OpenAPI 模式进行扩展。字段名 MUST 以 x- 开头,例如
x-internal-id。以 x-oai- 和 x-oas- 开头的字段名保留供 OpenAPI Initiative 定义的用途使用。值可以是任何有效的 JSON
值(null、原语、数组或对象)。
|
OpenAPI Initiative 维护多个 扩展注册表,包括针对 单个扩展关键字 和 扩展关键字命名空间 的注册表。
扩展是验证拟议添加项可行性的最佳方式之一。因此 RECOMMENDED 实现应被设计为可扩展以支持社区实验。
对任一扩展的支持为 OPTIONAL,对一个扩展的支持并不意味着对其他扩展的支持。
OpenAPI 描述使用 JSON、YAML 和 JSON Schema 的组合,因此它们共享相应的安全注意事项:
此外,OpenAPI 描述会被各种工具以多种用途处理,例如客户端代码生成、文档生成、服务端路由和 API 测试。OpenAPI 描述作者必须考虑 OpenAPI 描述可能被使用的场景所带来的风险。
OpenAPI 描述说明了用于保护其定义资源的安全方案。可用的安全方案提供不同程度的保护。数据的敏感性和安全漏洞可能带来的影响等因素应指导 API 资源安全方案的选择。有些安全方案(例如 basic auth 和 OAuth 隐式流程)是为与现有 API 兼容而支持的。然而,在 OpenAPI 中包含它们并不意味着对其使用的认可,尤其是在处理高度敏感的数据或操作时。
将 Security Requirement Object 连接到 Security Scheme Object(位于 Components Object 下)时的规则存在模糊之处,可能被利用。具体而言:
OpenAPI 规范中的某些对象 MAY 被声明但保持为空,或被完全移除,尽管它们本质上是 API 文档的核心。
其原因是允许在文档之上增加一层访问控制。尽管这不是规范本身的一部分,但某些库 MAY 选择基于某种形式的认证/授权来允许访问文档的部分内容。
两个例子:
OpenAPI 描述可能包含对外部资源的引用,消费工具可能会自动对其进行解引用。外部资源可能托管在不同且不受信任的域上。
OpenAPI 描述中的引用可能导致循环。工具必须检测并处理循环以防止资源耗尽。
某些字段允许使用 Markdown,而 Markdown 可能包含包括脚本在内的 HTML。适当清理 Markdown(sanitization)是工具的责任。
| 版本 | 日期 | 说明 |
|---|---|---|
| 3.2.0 | 2025-09-19 | 发布 OpenAPI 规范 3.2.0 |
| 3.1.2 | 2025-09-19 | OpenAPI 规范 3.1.2 的补丁发布 |
| 3.1.1 | 2024-10-24 | OpenAPI 规范 3.1.1 的补丁发布 |
| 3.1.0 | 2021-02-15 | 发布 OpenAPI 规范 3.1.0 |
| 3.1.0-rc1 | 2020-10-08 | 3.1 规范的 rc1 |
| 3.1.0-rc0 | 2020-06-18 | 3.1 规范的 rc0 |
| 3.0.4 | 2024-10-24 | OpenAPI 规范 3.0.4 的补丁发布 |
| 3.0.3 | 2020-02-20 | OpenAPI 规范 3.0.3 的补丁发布 |
| 3.0.2 | 2018-10-08 | OpenAPI 规范 3.0.2 的补丁发布 |
| 3.0.1 | 2017-12-06 | OpenAPI 规范 3.0.1 的补丁发布 |
| 3.0.0 | 2017-07-26 | 发布 OpenAPI 规范 3.0.0 |
| 3.0.0-rc2 | 2017-06-16 | 3.0 规范的 rc2 |
| 3.0.0-rc1 | 2017-04-27 | 3.0 规范的 rc1 |
| 3.0.0-rc0 | 2017-02-28 | 3.0 规范的实施者草案 |
| 2.0 | 2015-12-31 | 将 Swagger 2.0 捐赠给 OpenAPI Initiative |
| 2.0 | 2014-09-08 | 发布 Swagger 2.0 |
| 1.2 | 2014-03-14 | 正式文档的初始发布。 |
| 1.1 | 2012-08-22 | 发布 Swagger 1.1 |
| 1.0 | 2011-08-10 | 首次发布 Swagger 规范 |
将类型化数据序列化为纯文本(例如在 text/plain 消息体或 multipart 部分中,或在 URL 查询字符串或消息体中的
application/x-www-form-urlencoded 格式中)涉及大量由实现或应用定义的行为。
Schema Objects 基于 JSON Schema
数据模型 对数据进行验证,该模型仅识别四种原始数据类型:字符串(通常仅作为 UTF-8 具有良好互操作性)、数字、布尔值和
null。值得注意的是,整数并不是与其它数字不同的独立类型,type: "integer" 只是一个数学上的便利,而不是基于字符串表示中是否包含小数点来区分。
Parameter Object、Header Object 和 Encoding Object 提供了控制如何排列数组或对象类型值的功能。它们还可以控制如何对字符串进行进一步编码以避免保留或非法字符。然而,对于将经模式验证的非 UTF-8 原始数据类型(或整个数组或对象)转换为字符串,并没有通用规范。
有两种情况提供基于标准的指导:
null)在展开过程中被视为 未定义,因此被特别处理。
RFC6570 的实现通常对非字符串值的转换有自己的约定,但这些是实现特定的,不由 RFC 本身定义。这也是 OpenAPI 将这些转换留给实现定义的原因之一:它允许使用任意 RFC6570 实现而无需依赖其具体转换策略。
为了更精确地控制数字、布尔值和 null(或 RFC6570 视为未定义的其他值)的序列化,可以将模式定义为 type: "string" 并使用
pattern、enum、format
等关键字来约束,以指示应用在模式验证前必须如何预先转换其数据。得到的字符串就不需要进一步的类型转换。
format 关键字可以辅助序列化。一些格式(例如 date-time)是不含歧义的,而有些(例如格式注册表中的 decimal)则不够明确。然而,使用
format 时必须小心,确保相关工具支持特定格式,否则未识别的格式将被忽略。
要求输入为预格式化、模式验证通过的字符串也能改善往返互操作性,因为并非所有编程语言和环境都支持相同的数据类型。
在三种场景中,序列化以 [RFC6570] URI 模板来定义:
| 对象 | 条件 |
|---|---|
| Parameter Object | 当存在 schema 时 |
| Header Object | 当存在 schema 时 |
| Encoding Object | 当对 application/x-www-form-urlencoded 进行编码并使用任一
style、explode 或 allowReserved 时
|
本规范的实现 MAY 使用 RFC6570 的实现来执行变量展开,但有一些注意事项。
注意,当使用 style: "form" 的 RFC6570 展开来生成 application/x-www-form-urlencoded HTTP
消息体时,需要移除为满足 URI 查询字符串语法而产生的 ? 前缀。
当使用 style 等关键字来生成 multipart/form-data 消息体时,查询字符串名称被放在
Content-Disposition 部分头的 name 参数中,值被放在对应的部分体中;此时不使用 ?、=
和 & 字符,并且无论 allowReserved 的值如何,都不执行 URI 百分号编码。注意虽然 [RFC7578] 允许在“文件名”中使用 [RFC3986]
的百分号编码,但它并未在其它情况下处理格式内使用百分号编码。用户应当提供已经对名称和数据应用了符合 RFC7578 的必要转义。
注意并非所有 RFC6570 实现都支持全部四个级别的操作符,而这些级别都需要以完全支持 OpenAPI 规范的用法。使用支持级别较低的实现将需要额外手动构造 URI 模板以规避限制。
某些字段值可转换为 RFC6570 的 操作符(或无操作符):
| 字段 | 值 | 等价 |
|---|---|---|
| style | "simple" |
n/a |
| style | "matrix" |
; 前缀操作符 |
| style | "label" |
. 前缀操作符 |
| style | "form" |
? 前缀操作符 |
| allowReserved | false |
n/a |
| allowReserved | true |
+ 前缀操作符 |
| explode | false |
n/a |
| explode | true |
* 修饰符后缀 |
多个 style: "form" 参数等价于使用 ? 前缀操作符的单个 RFC6570 变量列表:
parameters:
- name: foo
in: query
schema:
type: object
explode: true
- name: bar
in: query
schema:
type: string
此示例等价于 RFC6570 的 {?foo*,bar},而 不等同 于
{?foo*}{&bar}。后者存在问题,因为如果 foo 未定义,结果将是无效 URI。Parameter Object 中没有等价的
& 前缀操作符。
注意 RFC6570 并未为超出 explode 所处理的单层复合值指定行为。对对象或数组使用在没有明确行为的情况下,其结果由实现定义。
RFC6570 展开使用的分隔符(例如用于将数组或对象值与 style: "simple" 一起连接的 ,)在
allowReserved 为 false 时会被自动百分号编码。注意由于 RFC6570 并未定义基于 URI
模板解析变量的方法,用户必须先按分隔符拆分值,然后再对可能包含分隔符字符的值进行百分号解码。
当 allowReserved 为 true 时,必须在正确的时机手动执行百分号编码(在连接值之前)和百分号解码(在按分隔符拆分之后)。
关于在没有 RFC6570 等价物的 style 值中处理作为分隔符而需要百分号编码的字符的更多指导,请参见 附录 E。
对没有直接 [RFC6570] 等价物的配置,应该(SHOULD)依照 RFC6570
处理。实现 MAY 使用 RFC6570 的常规或保留扩展(基于 allowReserved)为单独名称和值创建正确分隔的 URI
模板变量以绕过限制。
这包括:
pipeDelimited、spaceDelimited 和 deepObjectform 样式与 allowReserved: true 组合使用,该组合不允许,因为一次只能使用一个前缀操作符Parameter Object 的 name 字段的语法比 RFC6570 的 变量名语法 要宽松得多。包含 RFC6570 变量字符集之外字符的参数名 MUST 在用于 URI 模板之前进行百分号编码。
假设我们想在表单查询字符串中使用以下数据,其中 formulas 被展开,而 words 则不被展开:
formulas:
a: x+y
b: x/y
c: x^y
words:
- math
- is
- fun
此数组的 Parameter Objects 使用常规的 style: "form" 展开,RFC6570 完全支持:
parameters:
- name: formulas
in: query
schema:
type: object
additionalProperties:
type: string
explode: true
- name: words
in: query
schema:
type: array
items:
type: string
这翻译为以下 URI 模板:
{?formulas*,words}
用之前给定的数据展开,我们得到:
?a=x%2By&b=x%2Fy&c=x%5Ey&words=math,is,fun
但现在假设(出于某种原因),我们确实希望 b 公式中的 / 在查询字符串中保持原样,并且希望我们的单词像书写短语那样以空格分隔。为此,我们将对
formulas 添加 allowReserved: true,并将 words 的样式改为
style: "spaceDelimited":
parameters:
- name: formulas
in: query
schema:
type: object
additionalProperties:
type: string
explode: true
allowReserved: true
- name: words
in: query
style: spaceDelimited
explode: false
schema:
type: array
items:
type: string
我们不能结合 RFC6570 的 ? 和 + 前缀,而且 RFC6570 也无法将 ,
分隔符替换为空格。因此我们需要重构数据以适配手工构造的 URI 模板,使其以正确的方式通过不同类型的展开。
下面是一个这样的模板,使用约定 words.0 表示 words 的第一个条目,words.1 表示第二个,words.2
表示第三个:
?a={+a}&b={+b}&c={+c}&words={words.0} {words.1} {words.2}
RFC6570 提到使用 . “表示子结构中的名称层级”,但并未定义具体的命名约定或行为。由于 .
的使用不是自动的,我们需要为该新模板构造合适的输入结构。
我们还需要对 formulas 的值进行预处理,因为尽管 / 和大多数保留字符在 RFC3986 的查询字符串中是允许的,但
[、] 和 # 是不允许的,并且在
application/x-www-form-urlencoded 格式中 &、= 和
+ 都具有特殊行为(正是我们在查询字符串中使用的格式)。
设置 allowReserved: true 并不会使 URI 中不允许的保留字符变为允许,它只是允许它们在展开时被
原样传递,例如因为其他规范对它们定义了特定含义。
因此,用户仍需对那些未因特殊含义而被传递的保留字符进行百分号编码,因为保留展开无法判断哪些保留字符应保留,哪些仍应被百分号编码。不过,保留展开(与常规展开不同)会保留预先百分号编码的三元组不变。另请参见
附录 E
获取关于百分号编码与表单媒体类型的更多指导,包括在参数名和值中处理 spaceDelimited、pipeDelimited 和
deepObject 分隔符字符的建议。
下面是我们的数据结构,将名称和值安排为适合上述模板,其中 formulas 的值已对 []#&=+ 进行了预百分号编码(尽管在本示例中仅出现了
+):
a: x%2By
b: x/y
c: x^y
words.0: math
words.1: is
words.2: fun
用我们重新构造的数据展开手工组装的模板,得到以下查询字符串:
?a=x%2By&b=x/y&c=x%5Ey&words=math%20is%20fun
其中 / 和预先百分号编码的 %2B 被保留,但值中不允许的字符 ^ 和模板中但不在扩展变量内的空格字符被百分号编码。
在手动构造模板时,必须小心正确处理 RFC6570 所视为 未定义 的值:
formulas: {}
words:
- hello
- world
将这些数据与我们最初的 RFC6570 友好 URI 模板 {?formulas*,words} 一起使用,会产生:
?words=hello,world
这意味着手工构造的 URI 模板和重构后的数据需要完全省略 formulas 对象,以便 words 参数成为查询字符串中的第一个且唯一的参数。
重构后的数据:
words.0: hello
words.1: world
手工构造的 URI 模板:
?words={words.0} {words.1}
结果:
?words=hello%20world
在此示例中,心形表情符号在 URI 模板名称(或 URI)中并不合法:
parameters:
- name: ❤️
in: query
schema:
type: string
我们不能直接将 ❤️: "love!" 传递给 RFC6570 实现。相反,我们必须在数据和 URI 模板中预先对名称进行百分号编码(该心形为一个六字节的 UTF-8 序列):
"%E2%9D%A4%EF%B8%8F": love!
{?%E2%9D%A4%EF%B8%8F}
这将展开为:
?%E2%9D%A4%EF%B8%8F=love%21
HTTP 头在允许哪些字符以及如何对某些或全部不允许字符进行转义并包含方面规则不一致。虽然 [RFC9110] 中给出的 quoted-string ABNF
规则(见 第 5.4.6
节)是最常见的转义方案,但它并不足以普遍适用。例如,强实体标签(strong ETag)看起来像
"foo"(带引号,不论内容如何),而弱实体标签(weak ETag)看起来像
W/"foo"(注意只有部分值被引用);对于该头的引号内容,其转义方式也不同于 quoted-string 内容的转义。
因此,通过 Parameter 或 Header 对头传递的任何数据,需要在传给 OAS 实现之前先进行引号和转义,并且解析后的头值应包含引号和转义内容。
注意: 在本节中,为了可读性,application/x-www-form-urlencoded 和
multipart/form-data 媒体类型分别缩写为 form-urlencoded 和
form-data。
百分号编码用于 URI 以及其语法来源于 URI 的媒体类型。 百分号编码的基本规则如下:
+ 字符如何解码取决于你使用的是 application/x-www-form-urlencoded 规则还是更通用的 URI
规则;这是唯一可能因解码算法选择而改变结果的情况。本附录其余部分基于上述规则提供更详细的指导。
本过程涉及三类字符,这些名称在不同规范中有所不同,但在本节中定义如下:
form-urlencoded 对
=、& 和 + 定义了特殊行为)。
除非另有说明,本节采用 RFC3986 对 reserved 和 unreserved 的定义,并将不属于这两类的所有字符定义为 unsafe 集合。
每个 URI 组件(例如查询字符串)将部分保留字符视为不安全,要么因为它们在组件之间作为分隔符(例如 #),要么因为(如 [ 和
])历史上被视为全局不安全但后来为有限目的赋予了保留地位。
在某个组件内没有定义特殊含义的保留字符可以保持未百分号编码。然而,其他规范可以为这些字符定义特殊含义,要求在那些特殊含义之外的情形对这些字符进行百分号编码。
form-urlencoded 媒体类型将 = 和 & 定义为分隔符,并将 +
定义为空格的替代表示(而不是其百分号编码形式 %20)。
这意味着虽然这三者在 RFC3986 中作为保留但在查询字符串中被允许,但在 form-urlencoded 查询字符串中,它们必须被百分号编码,除非它们用于
form-urlencoded 的特殊用途;关于在表单值中处理 + 的示例,见 附录 C。
[RFC7578] 第 2 节 建议使用基于 RFC3986
的百分号编码作为一种机制,以将诸如文件名等按部分的基于文本的头数据保持在 ASCII 字符集内。
该建议并非旧的(2015 年之前的)form-data 规范的一部分,因此必须小心以确保互操作性。
希望以这种方式使用百分号编码的用户 MUST 以百分号编码的形式提供数据,因为对于该媒体类型,无论使用哪个 Encoding Object
字段,都不会自动应用百分号编码。
form-data 媒体类型允许其各部分包含任意文本或二进制数据,因此通常不需要百分号编码或类似的转义。
URI 百分号编码与 form-urlencoded 媒体类型具有复杂的规范历史,跨越多个修订版,在某些情况下,不同标准机构之间还存在所有权主张冲突。
不幸的是,这些规范各自定义了略有不同的百分号编码规则,如果 URI 或 form-urlencoded 消息体将受到严格验证,则需要考虑这些差异。
(请注意,许多 URI 解析器默认不会执行验证,或者根本不执行验证。)
本规范规范性地引用以下相关标准:
| 规范 | 日期 | OAS 用途 | 百分号编码 | 说明 |
|---|---|---|---|---|
| [RFC3986] | 01/2005 | URI/URL 语法,包括非 form-urlencoded 的基于内容的序列化 |
[RFC3986] | 取代了 [RFC1738] 和 [RFC2396] |
| [RFC6570] | 03/2012 | 基于 style 的序列化 | [RFC3986] | 不使用 + 来表示查询字符串中的空格 |
| WHATWG-URL 第 5 节 | “活动”标准 | 基于内容的 form/url-encoded 序列化,包括 HTTP 消息内容 |
WHATWG-URL 第 1.3 节 | 取代了 [RFC1866]、[HTML401] |
当 schema 存在时,Parameter Object 中使用基于 style 的带百分号编码的序列化;当至少存在
style、explode 或 allowReserved 之一时,Encoding Object 中也使用基于 style
的序列化。
有关 RFC6570 的两种不同百分号编码方法的更多细节以及包含 + 的示例,请参见 附录 C。
基于内容的序列化由 Media Type Object 定义,并在 Parameter
Object 和 Header Object 中当存在 content 字段时使用;当
style、explode 和 allowReserved 字段缺失时,基于 contentType
字段,Encoding Object 也会使用基于内容的序列化。
用于 URI 时,每个部分根据媒体类型进行编码(例如 text/plain 或 application/json),随后必须为了在
form-urlencoded 字符串(在表单样式查询字符串中)或在其他 URL 组件用于一般 URI 时进行百分号编码,除非该媒体类型已经包含了 URI 百分号编码。
本规范的先前版本要求使用 [RFC1866] 及其对 [RFC1738] 的百分号编码规则,而不是使用 [WHATWG-URL]。
[WHATWG-URL] 的 form-urlencoded
规则代表了当前浏览器社区在该媒体类型上的共识,并避免了 RFC1866 中对 RFC1738 不清晰释述所引入的歧义。
需要与 RFC1866/RFC1738 保持一致性的用户应仔细检查其工具和库的行为。
WHATWG 是一个面向 Web 浏览器
的标准组织,它为浏览器上下文中的 URL 解析和序列化定义了“URL 活动标准”,包括 form-urlencoded 数据的解析与序列化。
WHATWG 关于查询字符串的百分号编码规则会根据查询字符串是否被视为 作为
form-urlencoded(在该情形下它要求比 [RFC1738]
更多的百分号编码)或作为通用语法的一部分(其要求与 [RFC3986] 不同)而有所不同。
本规范仅在 form-urlencoded 规范方面依赖 WHATWG。那些以其他方式使用查询字符串的实现应意识到,WHATWG 关于非
form-urlencoded 查询字符串规则与 RFC3986 之间的区别需要谨慎考虑,结合 WHATWG 的百分号编码集合及其对 URL 的有效 Unicode
代码点集合;详见 关于百分号编码和非法或保留分隔符。
百分号解码算法并不关心哪些字符曾被或未被百分号编码,这意味着按照任一规范进行百分号编码的 URI 都能被正确解码。
同样地,所有 form-urlencoded 解码算法只是对百分号解码算法添加了 +-表示空格的处理,因此无论采用哪种编码规范,解码都能工作。
然而,需要注意:如果 + 表示空格,则必须使用 form-urlencoded 解码;如果 +
本身表示字面值,则应使用常规的百分号解码。
用于 deepObject、pipeDelimited 和 spaceDelimited 样式的分隔符字符
[、]、| 和空格,均 MUST 被百分号编码以符合 [RFC3986] 的要求。
这要求用户在参数名称和值中以某种方式预先对这些字符进行编码,以便在使用这些样式时将它们与分隔符用途区分开来。
空格字符在所有相关标准的所有实现中始终是非法的,并且以某种方式被编码。
虽然可以使用 form-urlencoded 约定的 + 来将参数名称和值中的空格与作为分隔符的
spaceDelimited(其编码为
%20)区分开,但规范将解码定义为单次处理,使得在解码后的结果中无法区分不同用法,除非使用先基于一种分隔符分割再解码另一种分隔符的非标准解析算法。任何此类非标准解析方法都不会在所有工具间互操作。
某些环境在查询字符串中使用未编码的 [、],甚至可能使用 |,且似乎没有出现问题。WHATWG 的通用查询字符串规则在非
form-urlencoded 的查询字符串中不要求对它们进行百分号编码,尽管它也将它们排除在 URL 的有效 Unicode 代码点集合之外。
依赖在名称和值中对这些分隔符保持未编码但在其它位置使用常规百分号编码的代码,不能保证在所有实现间互操作。
为获得最大互操作性,RECOMMENDED 的做法是:在对这些样式的分隔符进行百分号编码的同时,定义并记录一个额外的转义约定,或完全避免使用这些样式。 额外编码/转义的具体方法由 API 设计者决定,预期在本规范描述的序列化和编码步骤之前执行该预处理,并在对这些步骤反向处理时再将其还原。 这样可以将其保持在本规范所管理流程之外。
本节展示四种可能的基本 URI 来源中的每一种,随后举例说明带相对 $self 和 $id 的情况。
资源内容内的基本 URI(参见 [RFC3986] 第 5.1.1 节)是基本 URI 的最高优先级来源。
对于 OpenAPI 文档,此来源是 OpenAPI Object 的 $self 字段;对于包含 $id 的 Schema Object,或为包含
$id 的 Schema Object 的子模式,该来源是其 $id 字段:
假定下列文档的检索 URI 为 file://home/someone/src/api/openapi.yaml:
openapi: 3.2.0
$self: https://example.com/api/openapi
info:
title: Example API
version: 1.0
paths:
/foo:
get:
requestBody:
$ref: "shared/foo#/components/requestBodies/Foo"
假定下列文档的检索 URI 为 https://git.example.com/shared/blob/main/shared/foo.yaml:
openapi: 3.2.0
$self: https://example.com/api/shared/foo
info:
title: Shared components for all APIs
version: 1.0
components:
requestBodies:
Foo:
content:
application/json:
schema:
$ref: ../schemas/foo
schemas:
Foo:
$id: https://example.com/api/schemas/foo
properties:
bar:
$ref: bar
Bar:
$id: https://example.com/api/schemas/bar
type: string
在此示例中,检索 URI 无关紧要,因为两个文档都定义了 $self。
第一个文档中的相对 $ref 会基于 $self 解析为
https://example.com/api/shared/foo#/components/requestBodies/Foo。
该 URI 中 # 之前的部分匹配第二个文档的 $self,因此引用目标解析为该第二个文档中的
#/components/requestBodies/Foo。
在该文档中,请求体对象内的 $ref 使用该文档的 $self 作为基本 URI 来解析,生成
https://example.com/api/schemas/foo。
该 URI 与 #/components/schemas/Foo/$id 处的 $id 匹配,因此指向该 Schema Object。
该 Schema Object 有一个子模式,其 $ref: bar 将相对于该 $id 解析为
https://example.com/api/schemas/bar,这又匹配 #/components/schemas/Bar/$id 处的
$id。
为保证互操作性,包含 $id 的 Schema Objects,或位于包含 $id 的 schema 之下的对象,MUST 由离它最近的此类 $id 来引用其非片段部分。
如 JSON Schema 规范所述,使用非最近的 $id 作为基 URI 并将该 $id 与 JSON 指针片段交叉并不可互操作。
另请注意,位于 #/components/schemas/Foo/properties/bar/$ref 的引用不可能仅使用 JSON 指针片段引用
#/components/schemas/Bar,因为 JSON 指针会相对于 https://example.com/api/schemas/foo
解析,而不是相对于 OpenAPI 文档的来自 $self 的基本 URI。
如果在内容内无法确定基本 URI,则下一个要搜索的位置是任何封装实体(参见 [RFC3986] 第 5.1.2 节)。
这在封装在 OpenAPI 文档内的 Schema Objects 中很常见。
一个 OpenAPI Object 本身被封装在另一个实体中的示例是 multipart/related 存档(参见 [RFC2557]),例如以下
multipart/related; boundary="boundary-example"; type="application/openapi+yaml" 文档。
注意这仅是一个示例,并不是本规范要求必须支持此类 multipart 文档或任何其他可封装 OpenAPI Object 的格式。
RFC2557 是为了允许将一组包含超链接的文档作为电子邮件附件发送而编写的,在这种情况下 multipart 附件不会有检索 URI(尽管该格式也可用于 HTTP)。
--boundary-example
Content-Type: application/openapi+yaml
Content-Location: https://example.com/api/openapi.yaml
openapi: 3.2.0
info:
title: Example API
version: 1.0
externalDocs:
url: docs.html
components:
requestBodies:
Foo:
content:
application/json:
schema:
$ref: "#/components/api/schemas/Foo"
schemas:
Foo:
properties:
bar:
$ref: schemas/bar
--boundary-example
Content-Type: application/schema+json
Content-Location: https://example.com/api/schemas/bar
{
"type": "string"
}
--boundary-example
Content-Type: text/html
Content-Location: https://example.com/api/docs.html
<html>
<head>
<title>API Documentation</title>
</head>
<body>
<p>Awesome documentation goes here</p>
</body>
</html>
--boundary-example
在此示例中,每个部分的 URI(也作为其基本 URI)来自该部分的 Content-Location 头,如 RFC2557 所规定。
由于 #/components/schemas/Foo 处的 Schema Object 未包含 $id,其子模式中的引用使用 OpenAPI 文档的基本
URI,该基本 URI 取自其在 multipart/related 格式中部分的 Content-Location 头。
生成的对 https://example.com/schemas/bar 的引用匹配第二个部分的 Content-Location 头,根据 RFC2557
允许在 multipart 存档中定位引用目标。
类似地,External Documentation Object 的 url 字段相对于来自 Content-Location 的基本 URI
解析,生成与第三个部分的 Content-Location 匹配的 https://example.com/api/docs.html。
如果前两种来源都未提供基本 URI,则下一个来源是检索 URI(参见 [RFC3986] 第 5.1.3 节)。
假定该文档从 https://example.com/api/openapis.yaml 检索到:
openapi: 3.2.0
info:
title: Example API
version: 1.0
components:
requestBodies:
Foo:
content:
application/json:
schema:
$ref: schemas/foo
假定此 JSON Schema 文档从 https://example.com/api/schemas/foo 检索到:
{
"type": "object",
"properties": {
"bar": {
"type": "string"
}
}
}
将 $ref: schemas/foo 相对于 OpenAPI 文档的检索 URI 解析,会生成
https://example.com/api/schemas/foo,即 JSON Schema 文档的检索 URI。
当在内存中构建的 OpenAPI 文档既没有 $self、也没有封装实体或检索 URI 时,应用可以通过假定一个默认基本 URI 来解析内部(仅片段)引用(参见 [RFC3986] 第 5.1.4 节)。
虽然此类内部解析在实践中可以在不选择基本 URI 的情况下执行,但选择一个(例如带随机生成 UUID 的 URN,如
urn:uuid:f26cdaad-3193-4398-a838-4ecb7326c4c5)可以避免将其作为特殊情况来实现。
让我们重新考虑本附录的第一个示例,但将 $self 和 $id 使用相对 URI 引用,并设置支持该相对用法的检索 URI:
假定下列内容从 https://staging.example.com/api/openapi 检索到:
openapi: 3.2.0
$self: /api/openapi
info:
title: Example API
version: 1.0
paths:
/foo:
get:
requestBody:
$ref: "shared/foo#/components/requestBodies/Foo"
假定下列文档的检索 URI 为 https://staging.example.com/api/shared/foo:
openapi: 3.2.0
$self: /api/shared/foo
info:
title: Shared components for all APIs
version: 1.0
components:
requestBodies:
Foo:
content:
application/json:
schema:
$ref: ../schemas/foo
schemas:
Foo:
$id: /api/schemas/foo
properties:
bar:
$ref: bar
Bar:
$id: /api/schemas/bar
type: string
在此示例中,所有 $self 与 $id 值都是由绝对路径组成的相对 URI 引用。
这允许检索 URI 设置主机(和方案),在本例中为 https://staging.example.com,从而第一个文档的 $self 为
https://staging.example.com/openapi,第二个文档的 $self 为
https://staging.example.com/api/shared/foo,相应的 $id 值为
https://staging.example.com/api/schemas/foo 和
https://staging.example.com/api/schemas/bar。
此类相对的 $self 和 $id 值使得同一组文档在部署到其他主机时也能工作,例如生产环境的
https://example.com 或本地开发的 https://localhost:8080。
实现 MAY 支持以下任一方式的完整文档解析:
openapi 检测 OpenAPI 文档还可以使用额外机制来支持根节点为 OpenAPI Object 或 Schema Object 之外的对象的文档,但请注意其结果行为由实现定义:
在不考虑包含文档其余内容的情况下解析被引用的 OpenAPI 片段的实现,会错过可能改变引用目标含义和行为的关键字。 特别地,未考虑那些改变基本 URI 的关键字会引入安全风险,因为这会导致引用解析到非预期的 URI,产生不可预测的结果。 虽然一些实现因过去规范的要求而支持这种解析方式,但在 3.1 及以后的版本中,孤立片段解析的结果是 未定义 的,并且很可能与本规范的要求相冲突。
虽然可以构造某些 OpenAPI 描述以确保在将引用作为孤立片段解析时仍能正确工作,但依赖此行为 NOT RECOMMENDED。 本规范未明确列出在何种条件下此类行为是安全的,并且不保证在任何未来版本的 OAS 中继续保持安全。
OAD 中的 JSON 或 YAML 对象根据其上下文被解释为特定的对象类型(例如 Operation Objects、Response Objects、Reference Objects 等)。取决于引用的安排,给定的 JSON 或 YAML 对象可能在多种不同上下文中被解释:
如果相同的 JSON/YAML 对象被多次解析且各自上下文要求其被解析为不同的对象类型,则其结果行为为 实现定义,并且如果检测到可被视为错误(MAY)。例如,在期望 Path Item Object 的位置下引用位于 #/components/schemas 的空
Schema Object,因为空对象对两种类型都是有效的。为获得最大互操作性,RECOMMENDED OpenAPI 描述作者避免此类情形。
下列对象和字段涉及隐式连接的使用:
| 来源 | 目标 | 替代 |
|---|---|---|
Security Requirement Object {name}
|
Security Scheme Object 名称,位于 Components Object 下 | n/a |
Discriminator Object mapping
(隐式或显式名称语法)
|
Schema Object 名称,位于 Components Object 下 | mapping (显式 URI 语法) |
Operation Object tags |
Tag Object name(在 OpenAPI
Object 的 tags 数组中) |
n/a |
Link Object operationId |
Operation Object operationId |
operationRef |
另一个隐式连接涉及将 Paths Object 的模板化 URL 路径附加到相应 Server
Object 的 url 字段。
该连接无歧义,因为只有入口文档的 Paths Object 会为所描述的 API 提供 URL。
Security Requirement Object 与 Discriminator Object 中的隐式连接依赖于 组件名称,即 Components Object
中相应类型子对象所持有组件属性的名称。例如,位于 #/components/schemas/Foo 的 Schema Object 的组件名称为 Foo。
Operation Object 中 tags 的隐式连接使用 Tag Objects 的 name 字段,该字段(如 Components
Object)位于根 OpenAPI Object 下。这意味着解析组件名称和标签名称都依赖于从正确的 OpenAPI Object 开始。
对于从被引用(非入口)文档解析组件和标签名称连接,工具 RECOMMENDED 从入口文档解析,而不是从当前文档解析。 按 解析隐式连接 中建议的方式从入口文档解析组件和标签名称连接,允许在服务器对象顶层数组旁定义组件和 Tag Objects,并将其视为被引用文档访问的接口。
对于 Security Requirement Objects 和 Discriminator Objects,也可以通过使用这些对象提供的 URI 引用形式,将解析限制在被引用文档内。
Operation Object 的 tags 字段没有基于 URI 的替代方案。建议 OAD 作者使用外部方案(例如 OpenAPI Initiative 的 Overlay
规范)来模拟在多个文档间共享 Tag Objects。
本节展示如何检索一个可通过 HTTP 访问的多文档 OpenAPI 描述(OAD),并解析被引用(非入口)文档中的 Security Requirement Object。
Discriminator Object 的非 URI 映射和 Operation Object 的 tags 字段的行为遵循相同原则。
首先,入口文档是解析开始的地方。它将 MySecurity 安全方案定义为基于 JWT,并将一个 Path Item 定义为对另一个文档中组件的引用:
GET /api/description/openapi HTTP/1.1
Host: www.example.com
Accept: application/openapi+json
"components": {
"securitySchemes": {
"MySecurity": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
},
"paths": {
"/foo": {
"$ref": "other#/components/pathItems/Foo"
}
}
GET /api/description/openapi HTTP/1.1
Host: www.example.com
Accept: application/openapi+yaml
components:
securitySchemes:
MySecurity:
type: http
scheme: bearer
bearerFormat: JWT
paths:
/foo:
$ref: 'other#/components/pathItems/Foo'
该入口文档引用了另一个文档 other,未使用文件扩展名。这样客户端可以在每个资源上选择可接受的格式,前提是两种表示都可用:
GET /api/description/other HTTP/1.1
Host: www.example.com
Accept: application/openapi+json
"components": {
"securitySchemes": {
"MySecurity": {
"type": "http",
"scheme": "basic"
}
},
"pathItems": {
"Foo": {
"get": {
"security": [
"MySecurity": []
]
}
}
}
}
GET /api/description/other HTTP/1.1
Host: www.example.com
Accept: application/openapi+yaml
components:
securitySchemes:
MySecurity:
type: http
scheme: basic
pathItems:
Foo:
get:
security:
- MySecurity: []
在 other 文档中,被引用的 Path Item 对该 Security Scheme MySecurity
有一个安全需求。入口文档中也存在同名的 Security Scheme。正如 解析隐式连接
一节所述,MySecurity 的解析具有实现定义的行为,但该节正式建议工具应从 入口文档 解析组件名称。与所有实现定义的行为一样,重要的是检查工具文档以确定支持哪种行为。