OpenAPI 规范 v3.2.0

版本 3.2.0

关于本文档的更多信息
此版本:
https://spec.openapis.org/oas/v3.2.0.html
最新发布版本:
https://spec.openapis.org/oas/latest.html
最新编辑草稿:
https://github.com/OAI/OpenAPI-Specification/
编辑者:
Henry Andrews
Jeremy Whitlock
Karen Etheridge
Lorna Mitchell
Marsh Gardiner
Miguel Quintero
Mike Kistler
Ralf Handl
Vincent Biret
前任编辑:
Ron Ratovsky
Darrel Miller
Mike Ralphson
Uri Sarid
Jason Harmon
Tony Tam
其他版本:
https://spec.openapis.org/oas/v3.1.2.html
https://spec.openapis.org/oas/v3.1.1.html
https://spec.openapis.org/oas/v3.1.0.html
https://spec.openapis.org/oas/v3.0.4.html
https://spec.openapis.org/oas/v3.0.3.html
https://spec.openapis.org/oas/v3.0.2.html
https://spec.openapis.org/oas/v3.0.1.html
https://spec.openapis.org/oas/v3.0.0.html
https://spec.openapis.org/oas/v2.0.html
参与
GitHub OAI/OpenAPI-Specification
提交 Bug
提交历史
Pull requests

什么是 OpenAPI 规范?

OpenAPI 规范(OAS)定义了一个标准的、与编程语言无关的 HTTP API 接口描述方式,使得人类和计算机都能在无需访问源代码、额外文档或检测网络流量的情况下,发现并理解服务的能力。只要通过 OpenAPI 正确定义,使用者就能以极少的实现逻辑理解并与远程服务交互。类似于底层编程中的接口描述,OpenAPI 规范消除了调用服务时的猜测工作。

本文档状态

本规范的权威出处为上方引用的 HTML 文件,标记为此版本

1. OpenAPI 规范

1.1 版本 3.2.0

本文件中的 “MUST”(必须)、 “MUST NOT”(不能)、 “REQUIRED”(要求)、 “SHALL”(应)、 “SHALL NOT”(不应)、 “SHOULD”(推荐)、 “SHOULD NOT”(不推荐)、 “RECOMMENDED”(建议)、 “NOT RECOMMENDED”(不建议)、 “MAY”(可以)和 “OPTIONAL”(可选)等关键词的解释,如 BCP 14 [RFC2119] [RFC8174] 所述,仅在这些词全部大写时适用。

本文件采用 Apache License, Version 2.0 许可协议。

2. 简介

OpenAPI 规范(OAS)定义了一个语言无关的标准 HTTP API 接口,允许人类和计算机无需访问源代码、文档或通过网络流量检查,就能发现并理解服务的能力。经过规范定义后,使用者可通过解析与序列化 HTTP 消息到 数据模型,以最少的实现逻辑与远程服务交互。

一个 OpenAPI 描述 (OAD) 可以被文档生成工具用于展示 API,代码生成工具用于各类编程语言的服务端和客户端生成,以及测试工具和众多其他场景。

有关 OpenAPI 的使用示例和更多文档,请访问 [OpenAPI-Learn]。

关于扩展注册表和 OpenAPI Initiative 发布的其他规范,以及本规范的权威渲染,请访问 spec.openapis.org

2.1 版本与弃用

OpenAPI 规范采用 major.minor.patch 的版本管理方式。major.minor 部分(如 3.1SHALL 指定 OAS 功能集;.patch 版本则是修正文档或提供说明,不增加功能集。支持 OAS 3.1 的工具 SHOULD 兼容所有 OAS 3.1.* 版本。工具 SHOULD NOT 区分 patch 版本,例如不区分 3.1.03.1.1

部分字段或功能可能被标记为 弃用(Deprecated)。 这些字段和功能仍属于规范,可以正常使用。 但 OpenAPI 描述作者建议尽量用新字段或新功能替换弃用项。

目前,弃用元素预计会保留到 OAS 下一个主版本。但未来的小版本可能会规定弃用元素后续移除的策略。

偶尔,OAS 的 minor 版本会因带来显著好处而做出部分非兼容性变更,前提是影响较小。

2.2 未定义与实现自定义行为

本规范认为某些情景属于未定义实现自定义行为。

所谓未定义行为,至少部分情况下可能导致与规范相悖的结果。这种定义多用于无法或不便检测矛盾的场景。各实现 MAY 为兼容历史或规范旧版本的模糊文本而支持未定义场景。这在不少情况下能产生正确结果,但 NOT RECOMMENDED 依赖于此,因为无法保证对所有工具乃至未来规范版本都有效,哪怕这些版本在其它方面与当前版本严格兼容。

实现自定义行为,是指规范对某要求允许多种符合规范但实现方式不同的策略。这样描述用于指代模糊要求,API 描述作者RECOMMENDED 应避免,以提升工具兼容性。与未定义行为不同,若能确保所有相关工具实现一致,则依赖实现自定义行为是安全的。

3. 格式

符合 OpenAPI 规范的 OpenAPI 文档本身是一个 JSON 对象,可用 JSONYAML 格式表示。本规范中的示例为简洁起见采用 YAML 展示。

规范中的所有字段名称均为区分大小写。作为 map 键使用的字段也包括在内,除非明确说明为不区分大小写

OAS 对象包含两类字段:声明名称的固定字段,以及声明名称模式的模式字段

模式字段在其所处对象中 MUST 唯一。

注意:虽然 API 可用 YAML 或 JSON 格式描述,但 API 请求和响应体以及其它内容没有强制为 JSON 或 YAML。

3.1 JSON 与 YAML 兼容性

为保持 YAML 与 JSON 的格式互转能力,YAML 1.2 版 RECOMMENDED 使用,同时遵循 [RFC9512] 第 3.4 节的补充约束。

规范旧版本建议将 YAML 限制为其“JSON”schema 规则集,但不少这种(名字虽是 JSON,但实际上不能被 JSON 表示的)值。OAD 作者 SHOULD NOT 依赖这类不兼容 JSON 的 YAML 值。

3.2 大小写敏感性

因 OpenAPI 规范中的大多数字段名和字段值都区分大小写,本文档会特别标注不敏感场景。但只要字段名或字段值与 HTTP 概念直接对应,其大小写敏感规则即遵循 HTTP,无论本文档是否特别说明。

3.3 富文本格式化

规范各处的 description 字段均支持 [CommonMark] markdown 格式。OpenAPI 工具渲染富文本时 MUST 至少支持 [CommonMark-0.27] 所述的 markdown 语法。工具 MAY 可忽略部分 CommonMark 或扩展特性以确保安全。

CommonMark 0.27 仅作为最低要求,允许工具在此基础上实现扩展,但这些扩展均属于实现自定义行为,无法保证互操作。OpenAPI 描述作者 SHOULD 考虑使用这些扩展时,在只支持最低要求的工具下的展示效果。

4. 对象与字段

本节描述了 OpenAPI 描述格式的结构。 此处内容是格式的唯一规范性描述。 spec.openapis.org 提供了 JSON Schema,仅供参考。 如果 JSON Schema 与本节内容有不同,则本节 MUST 被视为权威。

在以下描述中,如果某字段未被明确声明为 REQUIRED 或未使用 MUSTSHALL 描述,则可视为 OPTIONAL 可选项。

4.1 OpenAPI 对象

这是OpenAPI 描述的根对象。

4.1.1 固定字段

除了必需字段外,componentspathswebhooks 字段至少有一个 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 依赖此服务。

4.1.2 OpenAPI 描述结构

OpenAPI 描述OAD)正式描述了 API 的表层及语义。 一个 OAD MAY 可以由单一文档组成,也可以分散至多个文档,各文档可通过URI 引用隐式连接字段关联。

为保证解析行为明确,OAD 所有文档 MUST 以 OpenAPI 对象或 Schema 对象为根,并 MUST 当作完整文档解析,具体见下一节。

根为其他对象或混杂其他内容的文档 MAY 可被支持,但会有实现自定义行为或潜在未定义行为,详见 附录 G:解析与解析指导。 除非另行说明,本规范假定文档根为 OpenAPI 或 Schema 对象。

对于多文档 OAD,包含 OpenAPI 对象且开始解析的文档称为 OAD 的入口文档。 强烈建议 RECOMMENDED OAD 入口文档命名为 openapi.jsonopenapi.yaml

OpenAPI 对象 MAY 可嵌入其他格式中,被称为嵌入格式,如 JSON Schema 是以 Schema 对象形式嵌入 OAS。 嵌入格式需定义如何解析嵌入内容,OAS 实现未声明嵌入格式支持时,不应期望能正确解析嵌入式 OAS 内容。

4.1.2.1 文档解析

OAD 中每个文档 MUST 完全解析,以定位可能的引用目标。 包括对 JSON Schema 规范(2020-12草案)的解析要求,并根据URI 相对引用对基础 URI 做修改。 引用目标由字段如 OpenAPI 对象的 $selfSchema 对象$id$anchor$dynamicAnchor 关键字定义。

工具 MUST NOT 在完全解析所有可作为 OAD 部分的文档前,将某引用视为无法解析。

如在解析引用时只解析了文档的一部分,则行为为实现自定义或未定义;参见 碎片化解析警告附录 G 详细说明。

4.1.2.2 API 描述 URI 的相对引用

OpenAPI 描述内用于引用、外部文档或如许可证等补充信息的 URI 作为标识符被解析,规范中称为 URI,与API URL区分。注意部分 URI 字段因历史原因名为 url,但描述采用正确的“URI”术语。

文档解析所述,多个字段可用于将 OpenAPI 文档或 Schema 对象关联到 URI,该 URI 不一定与文档或 schema 的实际位置一致。这样在不同部署环境(如本地文件系统,安全或网络受限环境)下可使用相同引用。

除非另行说明,所有作为 URI 的字段 MAY 接受 [RFC3986] 第 4.2 节 定义的相对引用。

4.1.2.2.1 基础 URI 的建立

相对 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,以便像实际获取一样解析引用。

4.1.2.2.2 URI 片段解析

如 URI 包含片段标识符,则片段应按所引用文档的片段解析机制解析。引用文档为 JSON 或 YAML 时,片段标识符 SHOULD 按 [RFC6901] 作为 JSON 指针解析。

4.1.2.2.3 CommonMark 字段中的相对 URI 引用

CommonMark 超链接中的相对引用在其渲染上下文中解析,可能与 API 描述上下文不同。

4.1.2.3 隐式连接解析

本规范的若干特性要求解析某些非 URI 连接至 OAD 其它部分。

在单文档 OAD 中这些连接可明确解析;在多文档 OAD 下,解析过程属于实现自定义,但须符合本节约束。 部分情况下可用明确的 URI 替代,强烈建议 OAD 作者 RECOMMENDED 使用 URI 以提升工具兼容性。

解析来自引用(非入口)文档的 Components 对象Tag 对象名称时,建议工具 RECOMMENDED 从入口文档解析而不是当前文档。解析基于 operationIdOperation 对象时,建议同时考虑所有已解析文档中的 Operation 对象。

隐式连接解析不影响 URI 解析 及其目标。

更多细节及使用隐式连接的对象和字段清单详见 附录 G:解析与解析指导

4.2 信息对象

该对象提供 API 元数据。 元数据 MAY 可被客户端在需要时使用,也 MAY 可在编辑或文档生成工具中展示以提升便捷性。

4.2.1 固定字段

字段名 类型 说明
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 可通过规范扩展扩展。

4.2.2 信息对象示例

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

4.3 Contact Object

暴露的 API 的联系信息。

4.3.1 Fixed Fields

字段名 类型 说明
name string 联系人或组织的标识名称。
url string 联系信息的 URI。该值 MUST 必须为 URI 形式。
email string 联系人或组织的电子邮件地址。该值 MUST 必须为电子邮件地址形式。

该对象 MAY 可通过 Specification Extensions 进行扩展。

4.3.2 Contact Object Example

name: API Support
url: https://www.example.com/support
email: support@example.com

4.4 License Object

暴露的 API 的许可信息。

4.4.1 Fixed Fields

字段名 类型 说明
name string REQUIRED。API 使用的许可证名称。
identifier string 用于 API 的 [SPDX-Licenses] 表达式。identifier 字段与 url 字段互斥。
url string API 所使用许可证的 URI。该值 MUST 必须为 URI 形式。url 字段与 identifier 字段互斥。

该对象 MAY 可通过 Specification Extensions 进行扩展。

4.4.2 License Object Example

name: Apache 2.0
identifier: Apache-2.0

4.5 Server Object

表示一个 Server 的对象。

4.5.1 Fixed Fields

字段名 类型 说明
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 进行扩展。

4.5.2 Relative References in API URLs

API 端点按定义作为位置进行访问,本规范将其描述为 URLs

除非另有说明,所有作为 URL 的字段 MAY 接受 [RFC3986] 第 4.2 节 定义的相对引用。

由于 API 与 OpenAPI 文档是不同的实体,RFC3986 对 OpenAPI 文档的基础 URI 规则不适用。除非另有说明,相对引用应使用 Server Object 中定义的 URL 作为基础 URL 来解析。注意这些 URL 本身 MAY 相对于引用它们的文档为相对。

4.5.2.1 Examples of API Base URL Determination

假设以下 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

4.5.3 Server Object Example

单个服务器可描述为:

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

4.6 Server Variable Object

表示用于服务器 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

此处的 literalspct-encodeducschariprivate 定义取自 [RFC6570],并结合了 Errata 6937literals 的修正。

每个服务器变量在 URL 模板中 MUST NOT 不得出现多次。

关于构造完整请求 URL 的指导,请参见 Paths Object

4.6.1 Fixed Fields

字段名 类型 说明
enum [string] 当替换选项来自有限集合时使用的字符串枚举。该数组 MUST NOT 不得为空。
default string REQUIRED。用于替换的默认值,若未提供替代值,则 SHALL 发送此默认值。如果定义了 enum,则该值 MUST 必须存在于枚举值中。注意此行为不同于 Schema Object 中的 default 关键字,后者记录接收方的行为而不是将值插入数据中。
description string 服务器变量的可选描述。[CommonMark] 语法 MAY 可用于富文本表示。

该对象 MAY 可通过 Specification Extensions 进行扩展。

4.7 Components Object

包含一组可重用对象以用于 OAS 的不同方面。所有在 Components Object 中定义的对象,除非在 Components 之外被显式引用,否则不会对 API 产生任何影响。

4.7.1 Fixed Fields

字段名 类型 说明
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

4.7.2 Components Object Example

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

4.8 Paths 对象

保存指向各个端点及其操作的相对路径。该路径会附加到来自 Server Object 的 URL 上以构造完整的 URL。由于 访问控制列表(ACL)约束,Paths Object MAY 可以为空。

4.8.1 模式字段

字段模式 类型 描述
/{path} Path Item 对象 指向单个端点的相对路径。字段名 MUST 以正斜杠(/)开头。来自 Server Objecturl 字段在解析并替换模板变量后,会将该路径追加(不进行相对 URL 解析)到其上以构造完整的 URL。允许使用 路径模板化。在匹配 URL 时,具体(非模板化的)路径会先于其模板化的对应项被匹配。具有相同层级但模板名称不同的模板化路径 MUST NOT 共存,因为它们是相同的。若出现歧义匹配,由工具决定使用哪一个。

该对象 MAY 可通过 规范扩展 进行扩展。

4.8.2 路径模板化

路径模板化指使用以大括号({})分隔的模板表达式,将 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          = "!" / "$" / "&" / "'" / "(" / ")"
                    / "*" / "+" / "," / ";" / "="

此处的 pcharunreservedpct-encodedsub-delims 定义取自 [RFC3986]。path-template 直接源自 RFC 3986,第 3.3 节

每个模板表达式在单一路径模板中 MUST NOT 出现多于一次。

另见 附录 C:使用基于 RFC6570 的序列化 以获取更多指导。

4.8.2.1 路径模板化匹配

假设存在如下路径,如果使用,则具体定义 /pets/mine 将优先匹配:

  /pets/{petId}
  /pets/mine

以下路径被视为相同且无效:

  /pets/{petId}
  /pets/{name}

以下情况可能导致歧义解析:

  /{entity}/me
  /books/{id}

4.8.3 Paths 对象示例

/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'

4.9 Path Item 对象

描述单一路径上可用的操作。由于 ACL 约束,Path Item MAY 为空。该路径本身仍会在文档查看器中显示,但查看者将无法知道哪些操作和参数可用。

4.9.1 固定字段

字段名 类型 描述
$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 包含重复参数。唯一参数由 namelocation 的组合定义。该列表可以使用 Reference Object 链接到在 OpenAPI Object 的 components.parameters 中定义的参数。

该对象 MAY 可通过 规范扩展 进行扩展。

4.9.2 Path Item 对象示例

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'

4.10 Operation 对象

描述路径上的单个 API 操作。

4.10.1 固定字段

字段名 类型 描述
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 包含重复参数。唯一参数由 namelocation 的组合定义。该列表可以使用 Reference Object 链接到在 OpenAPI Object 的 components.parameters 中定义的参数。
requestBody Request Body Object | Reference Object 适用于该操作的请求体。对于 HTTP 规范明确为请求体定义语义的 HTTP 方法(参见 HTTP 规范 [RFC9110] 第 9.3 节),requestBody 完全受支持。在其他 HTTP 规范不鼓励包含消息内容的情况(例如 GETDELETE),允许使用 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 ObjectOpenAPI Object 级别指定了 servers 数组,它们将被此值覆盖。

该对象 MAY 可通过 规范扩展 进行扩展。

4.10.2 Operation 对象示例

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

4.11 外部文档对象

允许引用外部资源以获取扩展文档。

4.11.1 固定字段

字段名 类型 描述
description string 目标文档的描述。可以使用 [CommonMark] 语法来进行富文本表示(MAY)。
url string REQUIRED。目标文档的 URI。此项 MUST 必须采用 URI 的形式。

该对象 MAY 可通过 规范扩展 进行扩展。

4.11.2 外部文档对象示例

description: Find more info here
url: https://example.com

4.12 参数对象

描述单个操作参数。

唯一参数由 namelocation 的组合定义。

有关百分号编码问题的详细探讨(包括与 application/x-www-form-urlencoded 查询字符串格式的交互),请参阅 附录 E

4.12.1 参数位置

in 字段指定的参数位置有五种:

  • path - 与 路径模板化 一起使用,参数值实际上是操作的 URL 的一部分。这不包括 API 的主机或基路径。例如,在 /items/{itemId} 中,路径参数是 itemId
  • query - 附加到 URL 的参数。例如,在 /items?id=### 中,查询参数是 idMUST NOTin: "querystring" 参数在同一操作(或该操作的 path-item)中同时出现。
  • querystring - 将整个 URL 查询字符串视为一个值的参数,该值 MUST 使用 content 字段指定,通常使用媒体类型 application/x-www-form-urlencoded 并使用 Encoding Objects,与该媒体类型的请求体相同;MUST NOT 出现多次,并且 MUST NOT 与任何 in: "query" 参数在同一操作(或该操作的 path-item)中同时出现。
  • header - 作为请求一部分期望的自定义头。注意 [RFC9110] 第 5.1 节 指出,头名称不区分大小写。
  • cookie - 用于将特定的 cookie 值传递给 API。

4.12.2 固定字段

参数的序列化规则通过两种方式中的一种指定。Parameter Objects MUST 包含 content 字段或 schema 字段,但不能同时包含两者。有关将各种类型的值转换为字符串表示的讨论,请参阅 附录 B

4.12.2.1 常用固定字段

这些字段 MAYcontentschema 一起使用。

exampleexamples 字段互斥;有关验证要求的指导,请参阅 Working with Examples

字段名 类型 描述
name string REQUIRED。参数的名称。参数名称区分大小写。
  • 如果 in"path",则 name 字段 MUST 对应于 Paths Objectpath 字段内出现的单个模板表达式。详见 Path Templating
  • 如果 in"header"name 字段为 "Accept""Content-Type""Authorization",则该参数定义 SHALL 被忽略。
  • 如果 in"querystring",或在某些 style 与 explode 组合 的情况下,参数序列化中不使用 name 的值。
  • 在所有其他情况下,name 对应于由 in 字段使用的参数名称。
in string REQUIRED。参数的位置。可能的值为 "query""querystring""header""path""cookie"
description string 参数的简短描述。可以包含使用示例。可以使用 [CommonMark] 语法进行富文本表示(MAY)。
required boolean 确定此参数是否为必需。如果参数位置为 "path",此字段为 REQUIRED,其值 MUSTtrue。否则,该字段 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"

4.12.2.2 schema 一起使用的固定字段

对于简单场景,schemastyle 可以描述参数的结构和语法。

这些字段 MUST NOTin: "querystring" 一起使用。

对于具有 schemain: "header"in: "cookie", style: "cookie" 的参数,需要注意:

  • 序列化这些值时,不应应用 URI 百分号编码(MUST NOT)。
  • 解析这些参数时,任何看起来像百分号编码的内容都不应被解码(MUST NOT)。
  • 如果使用的 RFC6570 实现自动执行编码或解码步骤,则在使用之前必须撤销这些步骤(MUST)。

在这些情况下,实现 MUST 原样传递值,而不是尝试对其进行引用或转义,因为头和 cookie 的引用规则与转义约定差异太大,无法自动处理;有关引用和转义的指导,请参见 附录 D

字段名 类型 描述
style string 描述参数值将如何根据参数类型进行序列化。默认值(基于 in 的取值):对于 "query""form";对于 "path""simple";对于 "header""simple";对于 "cookie""form"(出于兼容性原因;注意应与 in: "cookie" 一起使用 style: "cookie";详见 附录 D)。
explode boolean 当为 true 时,类型为 arrayobject 的参数会为数组的每个值或对象的每个键值对产生独立的参数。对于其他类型或当 style"deepObject" 时,此字段无效。若 style"form""cookie",默认值为 true;对于其他样式,默认值为 false
allowReserved boolean 当为 true 时,参数值按 [RFC6570] 定义的保留扩展进行序列化(参见 Section 3.2.3),这允许 RFC3986 的保留字符集以及百分号编码的三元组保持不变,同时对所有其他不允许的字符进行百分号编码(包括百分号 %,若其不属于百分号编码三元组)。应用仍需对目标位置或媒体类型不允许的保留字符进行百分号编码,或对 本规范不允许出现在路径中的字符 进行处理;详见 URL 百分号编码。默认值为 false。此字段仅适用于会自动进行百分号编码的 instyle 值。
schema Schema Object 定义参数使用类型的 schema。

另请参见 附录 C:使用基于 RFC6570 的序列化 以获取更多指导。

4.12.2.3 content 一起使用的固定字段

对于更复杂的场景,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 只能包含一项条目。

4.12.3 样式值

为了支持常见的简单参数序列化方式,定义了一组 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 中的 collectionFormatcsv 值。
form primitive, array, object query, cookie 表单样式参数,由 RFC6570 定义(参见 3.2.8 节)。此选项在 OpenAPI 2.0 中替代了 collectionFormatcsv(当 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 以转义形式提供。

4.12.4 URL 百分号编码

所有 API URL MUST 能够根据 [RFC3986] 的规则成功解析并进行百分号解码。

application/x-www-form-urlencoded 格式的内容,包括由具有 in: "query"Parameter Objects 生成的查询字符串,也 MUST 能够根据 [WHATWG-URL] 的规则成功解析并进行百分号解码,其中将未百分号编码的 + 视为已转义的空格字符。

这些要求以百分号解码规则来指定,这些规则在适用于 URI 的不同标准版本之间保持一致的容错性。

在若干场景下会执行百分号编码:

  • 由 [RFC6570] 实现(或其模拟,详见 附录 C)执行。
  • 当参数或 Encoding 对象将通过 Media Type Object 序列化的值合入时执行(若该媒体类型未包含 URI 百分号编码)。
  • 由用户在将数据传入 RFC6570 的保留扩展流程之前自行执行。

执行百分号编码时,最安全的方法是对 RFC3986 的“unreserved”集合之外的所有字符进行百分号编码;对于 form-urlencoded,还应对波浪号(~)进行百分号编码,以与源自 RFC1738 的历史要求保持一致。本规范中的示例采用了这种做法。

对于 form-urlencoded,尽管 [WHATWG-URL] 的算法要求将空格转义为 +,将空格百分号编码为 %20 也符合上述要求。在使用 RFC6570 的默认(非保留)表单样式扩展时,本规范示例会更倾向于使用 %20,否则使用 +

当保留字符用于保留用途(例如在 form-urlencoded 中的 &=+,或在 RFC6570 扩展中用于分隔非爆炸数组与对象值的 ,)时,不应对这些保留字符进行百分号编码(MUST NOT)。通过手动百分号编码将未编码的分隔符插入数据(包括通过 RFC6570 的保留扩展规则)所得结果是未定义的,并且可能导致实现无法将其解析回正确的数据结构。在某些情况下,例如将 / 插入路径参数值,本规范 明确禁止 这样做。

另见:

  • 附录 C,有关使用或模拟/扩展 RFC6570 实现的指导。
  • 附录 D,有关百分号编码与 cookies 的指导,以及头和 cookie 的其他转义方法。
  • 附录 E,对百分号编码选项、兼容性以及处理 OAS 定义的但不被 RFC3986 允许的分隔符的详尽讨论。

4.12.5 序列化与示例

本节的规则适用于 Parameter 与 Header 对象,它们使用相同的机制。

在展示序列化示例时,例如在 Example ObjectserializedValueexternalValue 字段中,在大多数情况下应显示实际序列化后的值,包含所有相关的百分号编码或其他编码/转义,并包括由 styleexplode 产生的任何分隔符。

在名称本身是构造序列化的一部分的情况下(例如由 style: "form" 生成的 name=value 对,或 style: "simple", explode: true 的组合),必须包含名称以及名称与值之间的任何分隔符(MUST)。

matrixlabel 样式会产生始终为有效序列化一部分的前导分隔符,该分隔符必须包含。对应 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

4.12.6 样式示例

假设名为 color 的参数有下列值之一,箭头右侧的内容表示在 Example Object 的 dataValue 字段中会显示的值:

   string -> "blue"
   array -> ["blue", "black", "brown"]
   object -> { "R": 100, "G": 200, "B": 150 }

下表展示了不同值的序列化示例(如在 Example Object 的 serializedValue 字段中所示)。

  • empty 表示空字符串,与 allowEmptyValue 字段无关。
  • 标记为 n/a 的组合其行为未定义。
  • undefined 列替代了以前规范中的 empty 列,以更好地与 RFC6570 的术语对齐,RFC6570 描述了包括但不限于 null 的“未定义”值具有特殊处理;值得注意的是,空字符串并非未定义。
  • 关于 form 与非 RFC6570 的查询字符串样式 spaceDelimitedpipeDelimiteddeepObject,请参见 附录 C,了解如何从多个参数构造查询字符串,以及参见 附录 D,了解关于 formcookie 参数的警告。
  • 示例根据上文的 URL 百分号编码 部分进行百分号编码;有关百分号编码问题的详细讨论请参见 附录 E,其中包括为什么未编码的 |%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

4.12.7 扩展对 Querystring 格式的支持

许多框架定义了用于复杂值的查询字符串语法,例如在参数名后追加数组索引或表示多层嵌套对象,这些超出了 deepObject 的能力范围。

由于这些并非标准且常互相冲突,OAS 并不尝试直接支持它们。对于使用 in: "querystring" 的此类格式,有两种可行途径:

  • 使用 content 并将媒体类型设为 text/plain,schema 为 type: "string",并在 OpenAPI 之外定义格式。虽然这需要更多的工作来描述和构造或解析该格式(从 OpenAPI 视角看这是一个普通字符串),但它提供了最灵活的选项。
  • 定义一种媒体类型(不必是 IANA 注册的),以及将内存中数据映射到该序列化媒体类型的过程。为提高跨工具支持的可能性,可将该媒体类型和过程提交至 OpenAPI Initiative 的 媒体类型注册表 进行注册。

4.12.8 参数对象示例

一个包含 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

4.13 Request Body Object

描述单个请求体。

4.13.1 Fixed Fields

字段名 类型 描述
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 进行扩展。

4.13.2 Request Body Examples

带有引用 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

4.14 Media Type Object

每个 Media Type Object 描述与其键所标识的媒体类型一致的内容结构。 可以使用多个 Media Type Object 来描述可出现在多种不同媒体类型中的内容。

当提供 exampleexamples 时,示例 SHOULD 与指定的 schema 匹配,并采用媒体类型及其编码所指定的正确格式。 exampleexamples 字段互斥。 有关以不同方式指定示例(包括非 JSON/YAML 值)的更多指南,请参见 Working With Examples

4.14.1 Fixed Fields

字段名 类型 描述
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] 属性名与其编码信息之间的映射,如 按名称编码 所定义。仅当媒体类型为 multipartapplication/x-www-form-urlencoded 时,encoding 字段 SHALL 生效。如果未为某属性提供 Encoding Object,则行为由 Encoding Object 的默认值决定。若存在 prefixEncodingitemEncoding,则该字段 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 进行扩展。

4.14.2 Media Types

媒体类型通过 IANA media types registry 以公开注册的方式记录,注册流程记录在 [RFC6838] 中。

API 有时也会定义私有媒体类型,例如 GitHub 的 application/vnd.github.v3+json(未注册),以及其他媒体类型如 application/schema+json 在被正式注册前已经被广泛使用。

有关在多种媒体类型下使用 schemas 的解析与序列化指南,请参见 Parsing and Serializing(位于 Schema Object 下)。

4.14.2.1 OpenAPI Media Type Registry

OpenAPI Initiative 维护了一个 Media Type Registry,汇总了本规范期望支持的媒体类型并索引了哪些章节讨论了哪些媒体类型。该注册表还链接到 IANA 注册(若存在)以及与每种媒体类型相关的最重要的规范文档。 在该注册表中作为扩展或为后续版本添加的任何附加媒体类型,MAY 被本版本 OAS 的实现所支持。

4.14.3 Complete vs Streaming Content

schema 字段 MUST 应用于完整内容,该完整内容由媒体类型和上下文(Request Body ObjectResponse ObjectParameter ObjectHeader Object)定义。 由于这需要将内容完整加载到内存中,因此对流式内容会带来挑战。 在客户端需要决定何时停止读取的用例尤其具有挑战性,因为流没有明确定义的结束。

4.14.3.1 Sequential Media Types

在本规范中,顺序媒体类型 定义为任何由重复结构组成且没有头部、尾部、信封或其它元数据附加到序列之外的媒体类型。

一些顺序媒体类型示例(包括一些未在 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

4.14.3.1.1 Streaming Sequential Media Types

itemSchema 字段用于支持顺序媒体类型的流式用例,itemEncoding 则为流式的 按位置的 multipart 媒体类型 提供对应的编码机制。

与应用于完整内容的 schema 不同(按 顺序媒体类型 节所述将其视为数组),itemSchema MUST 应用于流中每个项,这支持在从流中读取时对每个项进行逐个处理。

schemaitemSchemaMAY 在同一 Media Type Object 中使用。但这样做相较于在 schema 字段中使用 items 关键字通常并无显著优势。

4.14.3.2 Binary Streams

maxLength 关键字 MAY 用于设置由字符串数据(包括编码的二进制数据)或未编码的二进制数据组成的流式有效载荷的预计上限长度。对于未编码的二进制数据,长度以八位字节(octets)计。 在这种用例中,maxLength MAY 在常规 JSON Schema 验证之外被实现,因为 JSON Schema 并不直接适用于二进制数据,并且对编码的二进制流将其完整存于内存中可能不可行。

4.14.4 Special Considerations for Server-Sent Events

对于 text/event-stream,实现 MUST 在根据 text/event-stream specification 解析事件流后处理事件数据,包括忽略某些字段(包括注释)和/或值的所有指导,以及合并跨多行拆分的值的规则。

字段值类型 MUSTtext/event-stream 规范的规定处理(例如 retry 字段值被建模为预期为 JSON Schema type: integer 的 JSON 数字),而未给出显式值类型的字段 MUST 作为字符串处理。

一些 text/event-stream 的使用者在字段值中使用 JSON 格式,尤其是 data 字段。对于此类字符串编码数据的内容,请使用 JSON Schema 的关键词(尤其是 contentMediaTypecontentSchema)来描述并验证这些字段,以提供比基于字符串的验证(如 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

4.14.5 Encoding Usage and Restrictions

这些编码字段定义了如何将每个 Encoding Object 映射到数据中的具体值。 每个字段都有其可使用的媒体类型集;对于所有其它媒体类型,这三者在实现上 SHALL 被忽略。

4.14.5.1 Encoding By Name

encoding 字段的行为旨在支持 Web 表单,因此仅为结构为允许重复值的名-值对的媒体类型定义,最显著的是 application/x-www-form-urlencodedmultipart/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

4.14.5.2 Encoding By Position

大多数 multipart 媒体类型(包括定义解析所有 multipart 类型基础规则的 multipart/mixed)没有命名的部分。 这些媒体类型的数据被建模为数组,每个部分对应一个按序的项。

要使用 prefixEncoding 和/或 itemEncoding 字段,必须存在 itemSchema 或数组形式的 schema。 这些字段类似于 JSON Schema 的 prefixItemsitems 关键字,其中 prefixEncoding(若存在)提供一个 Encoding Object 数组,每个 Encoding Object 应用于数据数组中相同位置的值,而 itemEncoding 将其单个 Encoding Object 应用于数组中剩余的所有项。 与 prefixItems 一样,如果实例数组比 prefixEncoding 数组短,这并非错误;额外的 Encoding Objects SHALL 被忽略。

itemEncoding 字段也可与 itemSchema 一起使用以支持流式 multipart 内容。

4.14.5.3 Additional Encoding Approaches

prefixEncoding 字段可与任何 multipart 内容一起使用以强制固定的部分顺序。 这包括 multipart/form-data,对于此类情形,Encoding Object 的 headers 字段 MUST 用于提供 Content-Disposition 与部分名称,因为没有属性名可自动提供名称。

本规范的早期版本建议在非 multipart/form-datamultipart 媒体类型中使用每部分的 Content-Disposition: form-data 头的 name 参数 来规避 encoding 字段的限制。 实现 MAY 选择支持该变通方法,但由于该用法并不常见,非 form-data 类型的 multipart 媒体类型的实现很可能不会支持它。

4.14.6 Media Type Examples

有关表单相关与 multipart 媒体类型示例,请参见 Encoding Object

4.14.6.1 JSON

请注意,由于此示例以 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'
4.14.6.2 Sequential JSON

对于任何其序列项为 JSON 值的 顺序媒体类型,无需对每个值进行转换。 JSON 文本序列([RFC7464] 的 application/json-seq 以及 [RFC8091] 的 +json-seq 结构后缀)、JSON Linesapplication/jsonl)和 NDJSONapplication/x-ndjson)都属于此类。注意 JSON Lines 与 NDJSON 的媒体类型尚未在 IANA 注册,但被广泛使用。

下面示例展示了用于流式日志条目和响应查询时返回固定长度集合的 Media Type Objects,展示了 schemaitemSchema 之间的关系以及何时使用它们,尽管在两种情况下 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!"
}
4.14.6.3 Server-Sent Event Streams

在此示例中,假设在 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}"}

4.14.7 Considerations for File Uploads

与 OpenAPI 2.0 相比,OAS 3.x 中的 file 输入/输出内容使用与任何其他 schema 类型相同的语义进行描述。

与 OAS 3.0 不同,OAS 3.1 中 format 关键字对 schema 的内容编码不再产生影响。取而代之的是使用 JSON Schema 的 contentEncodingcontentMediaType 关键字。有关如何使用这些关键字建模各种场景以及如何从先前的 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 所示。

4.15 Encoding 对象

应用于单个值的单个编码定义,Encoding Objects 与值之间的映射由 Media Type Object 决定,详见 Encoding Usage and Restrictions

有关将各种类型的值转换为字符串表示的讨论,请参阅 Appendix B

有关表单媒体类型的百分号编码问题的详细检查,请参阅 Appendix E

4.15.1 固定字段

4.15.1.1 常用固定字段

这些字段 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 Objectencoding 字段相同的方式应用嵌套的 Encoding Objects。
prefixEncoding [Encoding Object] 以与 Media Type ObjectprefixEncoding 字段相同的方式应用嵌套的 Encoding Objects。
itemEncoding Encoding Object 以与 Media Type ObjectitemEncoding 字段相同的方式应用嵌套的 Encoding Objects。

该对象 MAY 可通过 Specification Extensions 进行扩展。

contentType 的默认值如下,其中 n/acontentEncoding 列中表示 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

4.15.1.2 用于 RFC6570 风格序列化的固定字段
字段名 类型 描述
style string 描述特定属性值将如何根据其类型进行序列化。关于 Parameter Objectstyle 字段的详细信息请参阅相应部分。其行为与 query 参数采用相同的取值,包括默认值 "form"(该默认仅在由于显式指定了 explodeallowReserved 而未使用 contentType 时适用)。注意用于查询字符串的初始 ?application/x-www-form-urlencoded 消息体中不使用,若使用 RFC6570 实现则 MUST 将其移除(若手动构造字符串则不要添加)。若媒体类型不是 application/x-www-form-urlencodedmultipart/form-data,则此字段 SHALL 被忽略。若显式定义了该值,则隐式或显式的 contentType SHALL 被忽略。
explode boolean 当为真时,类型为 arrayobject 的属性会为数组的每个值或映射的每个键值对生成独立的参数。对于其他类型的属性,或当 style"deepObject" 时,该字段无效。若 style"form",默认值为 true;其它样式默认值为 false。若媒体类型不是 application/x-www-form-urlencodedmultipart/form-data,此字段 SHALL 被忽略。若显式定义了该值,则隐式或显式的 contentType SHALL 被忽略。
allowReserved boolean 当为真时,参数值按 [RFC6570] 所定义的保留扩展进行序列化(参见 Section 3.2.3),这允许 RFC3986 的保留字符集以及百分号编码三元组保持不变,同时对所有其他不允许的字符进行百分号编码(包括百分号 %,若其不属于百分号编码三元组)。应用程序仍需对目标媒体类型不允许的保留字符进行百分号编码;详见 URL Percent-Encoding。默认值为 false。若媒体类型不是 application/x-www-form-urlencodedmultipart/form-data,此字段 SHALL 被忽略。若显式定义了该值,则隐式或显式的 contentType SHALL 被忽略。

当对 multipart/form-data 使用 RFC6570 风格序列化时,MUST NOT 应用 URI 百分号编码,且 allowReserved 的值无影响。 另见 Appendix C: Using RFC6570 Implementations 以获取额外指导。

注意:至少存在 styleexplodeallowReserved 中的任一显式值,相当于在 Parameter Objects 中使用 schemain: "query"。 若这三者都缺失,则等同于使用 content,但媒体类型由 contentType 指定,而非通过 Media Type Object 指定。

4.15.2 嵌套编码

需要编码的嵌套格式(最显著的是嵌套的 multipart/mixed)可以通过本对象的 encodingprefixEncoding 和/或 itemEncoding 字段来支持。 实现 MUST 支持一级嵌套,并且 MAY 支持更多级别的嵌套。

4.15.3 x-www-form-urlencoded 媒体类型的编码

要使用 [WHATWG-URL] 的表单 URL 编码规则处理内容,请在 Media Type Object 中使用 application/x-www-form-urlencoded 媒体类型。 这种配置意味着在任何复杂对象序列化为字符串表示之后,内容 MUST 按照该媒体类型的 [WHATWG-URL] 规则进行百分号编码。

有关表单媒体类型的百分号编码问题的详细检查,请参见 Appendix E

4.15.3.1 示例:包含 JSON 值的 URL 编码表单

当不存在 encoding 字段时,序列化策略基于 Encoding Object 的默认值:

requestBody:
  content:
    application/x-www-form-urlencoded:
      schema:
        type: object
        properties:
          id:
            type: string
            format: uuid
          address:
            type: object
            properties: {}

在此示例中,考虑一个 idf81d4fae-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
4.15.3.2 示例:包含二进制值的 URL 编码表单

注意 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

假设 nameexample,且 icon 为一个实心红色的 2x2 像素 PNG,则会产生如下请求体:

name=example&icon=iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAABGdBTUEAALGPC_xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAAqADAAQAAAABAAAAAgAAAADO0J6QAAAAEElEQVQIHWP8zwACTGCSAQANHQEDqtPptQAAAABJRU5ErkJggg%3D%3D

注意即使使用“URL safe”的 contentEncoding: base64url,末尾的 = 填充字符仍需进行百分号编码。 一些 base64 解码实现可能根据 [RFC4648] 第 3.2 节 能够在没有填充的情况下处理字符串,但这并不保证,因此保留填充并依赖百分号解码通常更具互操作性。

4.15.4 multipart 媒体类型的编码

关于将 schema 属性与各部分相关联的指导,请参阅 Encoding Usage and Restrictions

注意一般情况下 multipart 媒体类型对可用头部有显著限制(参见 [RFC2046] 第 5.1 节)以及对 multi-part/form-data 的特殊限制(参见 [RFC7578] 第 4.8 节)。

4.15.4.1 处理多个 contentType

当为 contentType 提供多个值时,解析仍然直接,因为文档中包含了该部分的实际 Content-Type

对于编码和序列化,实施应 MUST 提供机制让应用程序指明意图使用的媒体类型。 实现 MAY 选择提供媒体类型嗅探([SNIFF])作为替代,但由于该过程固有的安全风险,该方法 MUST NOT 成为默认行为。

4.15.4.2 Content-Transfer-EncodingcontentEncoding

对 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-dataContent-Transfer-Encoding 已被弃用(参见 [RFC7578] 第 4.7 节),因为 HTTP 已支持二进制数据。

有关表单媒体类型的百分号编码问题的详细检查,请参阅 Appendix E

4.15.4.3 示例:基本的 Multipart 表单

当不使用 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'
4.15.4.4 示例:包含 Encoding Objects 的 Multipart 表单

使用 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
4.15.4.5 示例:包含多个文件的 Multipart 表单

根据 [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

4.15.4.6 示例: 有序且无名的 Multipart

一个由 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/*
4.15.4.7 示例:有必需头部的有序 Multipart

如 [RFC2557] 所述,一组构成网页的资源可以在 multipart/related 有载荷中发送,通过为每个页面定义 Content-Location 头来保留从 text/html 文档到从属资源(脚本、样式表、图像等)的链接。 第一部分被用作根资源(除非使用 RFC2557 建议避免且在本示例中被禁止的 Content-ID),因此我们使用 prefixItemsprefixEncoding 来定义其必须是 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'
4.15.4.8 示例: 流式 Multipart

本例假设一个设备拍摄大量图片并将其流式传输给调用方。与前例不同,我们在此使用 itemSchema,因为期望每张图片在到达时(或少量批次)被处理,而缓冲整个流将占用过多内存。

multipart/mixed:
  itemSchema:
    $comment: A single data image from the device
  itemEncoding:
    contentType: image/jpg
4.15.4.9 示例: 流式字节范围

对于 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
4.15.4.10 示例: 嵌套的 multipart/mixed

此示例定义了一个两部分的 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

4.16 Responses 对象

用于描述某个操作预期的响应的容器。 该容器将 HTTP 响应代码映射到预期的响应。

文档不一定需要覆盖所有可能的 HTTP 响应代码,因为某些响应代码可能事先未知。 但文档应当覆盖成功操作的响应以及任何已知的错误。

default MAY 可用作 Responses Object 中未单独覆盖的所有 HTTP 代码的默认 Response Object。

Responses Object MUST 至少包含一个响应代码;如果只提供了一个响应代码,则该代码 SHOULD 为成功操作调用的响应。

4.16.1 固定字段

字段名 类型 描述
default Response Object | Reference Object 对未为特定 HTTP 响应代码声明的其它响应的文档。使用此字段来覆盖未声明的响应。

4.16.2 模式字段

字段模式 类型 描述
HTTP 状态码 Response Object | Reference Object 任意 HTTP 状态码 可用作属性名,但每个代码只能有一个属性,用以描述该 HTTP 状态码的预期响应。为兼容 JSON 与 YAML,此字段 MUST 用引号包围(例如,“200”)。要定义响应码范围,该字段 MAY 使用大写通配符字符 X,例如 2XX 表示所有 200 到 299 的响应代码。仅允许以下范围定义:1XX2XX3XX4XX5XX。若使用显式代码定义了某响应,则该显式定义优先于相应的范围定义。

该对象 MAY 可通过 规范扩展 进行扩展。

4.16.3 HTTP 状态码

HTTP 状态码用于指示已执行操作的状态。 应当从 IANA Status Code Registry 中注册的可用状态码中选择状态码,尽量遵循该注册表。

4.16.4 Responses 对象示例

一个用于成功操作的 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'

4.17 Response 对象

描述 API 操作返回的单个响应,包括基于该响应的设计时静态 links 到其它操作。

4.17.1 固定字段

字段名 类型 描述
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 可通过 规范扩展 进行扩展。

4.17.2 Response 对象示例

返回复杂类型数组的响应:

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

4.18 Callback 对象

与父操作相关的可能的带外回调映射。 映射中的每个值都是一个 Path Item Object,用于描述 API 提供者可能发起的一组请求以及预期的响应。 用于标识 Path Item Object 的键是一个在运行时求值的表达式,用来标识回调操作要使用的 URL。

若要描述来自 API 提供者的入站请求(独立于另一次 API 调用),请使用 webhooks 字段。

4.18.1 模式字段

字段模式 类型 描述
{expression} Path Item Object 用于定义回调请求和预期响应的 Path Item Object。可参见一个 完整示例

该对象 MAY 可通过 规范扩展 进行扩展。

4.18.2 键表达式

用于标识 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

4.18.3 Callback 对象示例

下面的示例使用用户提供的查询字符串参数 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

下面的示例展示了一个回调,其中服务器是硬编码的,但查询字符串参数由请求体中的 idemail 属性填充。

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

4.19 Example 对象

将内部或外部示例值与基本的 summarydescription 元数据分组的对象。 这些示例可以展示适用于 schema 验证的数据,或按包含的 Media Type ObjectParameter ObjectHeader Object 要求的序列化数据。 该对象通常用于名为 examples(复数)的字段,并且是可通过 Reference Object 引用的替代方案,弥补了旧的不可引用的单数 example 字段的不足。 在 Working With Examples 一节中对该对象的各字段与示例类型有更详细的说明。

4.19.1 固定字段

字段名 类型 描述
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),因为数据形式更易于处理。如果此字段存在,则 valueexternalValue MUST 缺失。
externalValue string 一个 URI,标识位于单独文档中的序列化示例,允许表达不能以 Unicode 字符串容易或可读地表示的值。如果存在 dataValue,则该字段 SHOULD 标识给定数据的某种序列化形式。否则,该值 SHOULD 为某个数据值的有效序列化,而该数据值本身应当按 dataValue 的描述 MUST 有效。若此字段存在,则 serializedValuevalue MUST 缺失。另见解析 相对引用 的规则。
value Any 嵌入的字面示例。valueexternalValue 互斥。对于无法自然以 JSON 或 YAML 表示的媒体类型示例,请使用字符串值包含示例并在必要时进行转义。

对非 JSON 序列化目标已弃用:请改用 dataValue 和/或 serializedValue,它们具有无歧义的语法和语义。

该对象 MAY 可通过 规范扩展 进行扩展。

在所有情况下,示例值 SHOULD 与其关联值的 schema 兼容。工具实现 MAY 选择自动验证兼容性,并在不兼容时拒绝示例值。有关“兼容”的确切含义,请参见 Validating Examples 一节中对本对象每个字段的定义。

4.19.2 使用示例

Example Objects 可用于 Parameter ObjectsHeader ObjectsMedia Type Objects。 在这三类对象中,均通过 examples(复数)字段来完成。但也有其它提供示例的方式:在 Parameter、Header 或 Media Type 对象中互斥的单数 example 字段,以及在出现在三个对象的 schema 字段中的 Schema Object 中的两个关键字(弃用的单数 example 与当前的复数 examples,后者接受示例数组)。 下文中我们将单数的简写 example 字段(在 Parameter、Header 或 Media Type 对象中,其行为等同于只有 value 字段的单一 Example Object)称为“简写 example”字段。每种字段都有稍微不同的考虑因素。

4.19.2.1 兼容 JSON 与 value-安全的示例

value 与简写 example 字段旨在具有与 serializedValue(或 externalValue)相同的语义,但在 JSON(或 JSON 兼容的 YAML)表示与最终序列化形式无差异时提供更方便的语法。当将此语法用于 application/json 或任何 +json 媒体类型时,这些字段实际上等同于 dataValue,因为序列化是平凡的,因此使用它们是安全的。

对于仅包含单个字符串的数据,且序列化目标如 text/plain 保证字符串以不需进一步转义的方式序列化时,这些字段也安全可用。

对于其它序列化目标,“自然地用 JSON 或 YAML 表示”的歧义性,以及先前参数样式示例表中的错误,导致这些字段在非 JSON 目标上的支持与用法存在不一致。因此,在实践中对于非 JSON 目标,value 与简写 example 字段的行为通常由实现定义;OAD 作者 SHOULD 使用其它字段以确保互操作性。

4.19.2.2 选择使用哪些字段

牢记上一节中的注意事项,以及当仅涉及一个 Example Object 时可用简写 example 代替 value 的事实,使用下列指南决定应使用哪一字段。

若要展示一个将如何被 Schema Object 验证的示例:

  • 如果意图是将示例随验证用的 schema 一起保留,请使用 Schema Object 的 examples 数组(来自 JSON Schema draft 2020-12)。
    • 仅当需要与 OAS v3.0 或更早版本兼容时,才使用 Schema Object 的单数 example
  • 如果意图是将示例与其序列化形式关联,或希望将示例与 schema 分离,请使用 Example Object 的 dataValue 字段。
    • 仅当需要与 OAS v3.1 或更早版本兼容且该值可“自然地在 JSON 或 YAML 中表示”而无需在验证就绪的值与序列化表示之间进行任何更改(例如百分号编码)时,才使用 Example Object 的 value 字段。

若要展示用于构建 HTTP/1.1 消息的序列化示例:

  • 如果序列化能表示为有效的 Unicode 字符串且无需展示确切字符编码,请使用 Example Object 的 serializedValue 字段。
    • 仅当需要与 OAS v3.1 或更早版本兼容时,才使用 value 的字符串形式。
  • 对于其它值,或希望将示例与 OpenAPI 文档分离,请使用 Example Object 的 externalValue

serializedValueexternalValue 两个字段都 MUST 展示数据的序列化形式。对于 Media Type Objects,这是一份合适媒体类型的文档,并应用任何 Encoding Object 的效果。对于使用 schemastyle(而不是 Media Type Object)的 Parameter 与 Header Objects,请参见 Style Examples,了解何为序列化值。

4.19.2.3 用于 serializedExample 的标准

若满足下列任一条件,则序列化可以在 serializedValue 中表示为有效的 Unicode 字符串:

  • 该媒体类型支持 charset 参数,并且该参数指示任何 Unicode 编码(UTF-8、UTF-16 等)或上述编码的有效子集(例如 US-ASCII)。
  • 该格式(例如 URI 或 HTTP 字段)或基于字符的媒体类型要求或默认使用 Unicode 编码,或其有效子集(如 US-ASCII),且未被 charset 覆盖。
  • 该格式为复合格式,且所有部分至少满足上述一项,例如一个包含 application/json(默认 UTF-8)和 application/xml; charset=utf-8multipart/mixed

在所有这些情况下,将 OAD 的字符集(假定为 JSON 的互操作字符集 UTF-8)先转换为 Unicode 代码点,再转换为实际序列化字符集的过程是可定义的。

对于 externalValue,若未显式声明字符集且格式或媒体类型规范也未确定字符集,实施者 SHOULD 假设为 UTF-8。

4.19.2.4 验证示例

工具实现 MAY 选择自动验证兼容性,并在不兼容时拒绝示例值。对于以 schema 就绪数据形式存在的示例,验证是直接且明确的。

对于序列化的示例,某些格式允许相同数据的多种有效表示形式(包括在 附录 B 中提到的场景)。在某些情况下,解析序列化示例并验证所得数据可以消除歧义,但在少数情况下解析本身也存在歧义。因此,OAD 作者应注意对某些序列化示例的验证在性质上属于尽力而为的特性。

4.19.3 Example 对象示例

4.19.3.1 JSON 示例

在编写 YAML 时,dataValue 可以使用 JSON 语法(如 noRating 示例所示),但并非必须。虽然此示例对于 JSON 展示了 dataValueserializedValue 的行为(在 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
          }
4.19.3.2 二进制示例

完整二进制数据使用 externalValue 展示:

content:
  image/png:
    schema: {}
    examples:
      Red:
        externalValue: ./examples/2-by-2-red-pixels.png
4.19.3.3 布尔查询参数示例

由于布尔值序列化无统一标准(参见 附录 B),本示例使用 dataValueserializedValue 来展示该参数的布尔序列化方式:

name: flag
in: query
required: true
schema:
  type: boolean
examples:
  "true":
    dataValue: true
    serializedValue: flag=true
  "false":
    dataValue: false
    serializedValue: flag=false

4.21 Header Object

描述用于 HTTP responses 以及用于 multipart 表示中的各部分 的单个 header;请参阅相关的 Response ObjectEncoding Object 文档以了解哪些头可以被描述的限制。

Header Object 遵循 Parameter Object 的结构,包括基于是否存在 schemacontent 来确定其序列化策略,但有如下更改:

  1. name MUST NOT 指定,名称由对应的 headers 映射给出。
  2. in MUST NOT 指定,其隐含位置为 header
  3. 所有受位置影响的特性 MUST 适用于位置为 header(例如 style)。这意味着 allowEmptyValue MUST NOT 被使用,且若使用 style,则 MUST 限定为 "simple"

4.21.1 Fixed Fields

4.21.1.1 Common Fixed Fields

这些字段 MAYcontentschema 一起使用。

exampleexamples 字段互斥;有关验证要求的指导,请参见 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 扩展。

4.21.1.2 Fixed Fields for use with schema

对于简单场景,schemastyle 可以描述 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 时,类型为 arrayobject 的 header 值将产生一个单一 header,其值为数组项或映射键值对的以逗号分隔的列表,参见 Style Examples。对于其他数据类型此字段无效。默认值为 false
schema Schema Object 定义用于该 header 的类型的 schema。

另见 Appendix C: Using RFC6570-Based Serialization 以获取更多指导。

4.21.1.3 Fixed Fields for use with content

对于更复杂的情形,content 字段可定义 header 的媒体类型和 schema,并提供其使用示例。

Field Name Type Description
content Map[string, Media Type Object | Reference Object] 包含 header 表示形式的映射。键是媒体类型,值描述该媒体类型。该映射 MUST 仅包含一项条目。

4.21.4 Header Object Example

一个简单的 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"'

4.22 标签对象

为单个标签添加由 Operation Object 使用的元数据。对于 Operation Object 实例中定义的每个标签,并非强制要求都存在一个 Tag Object。

4.22.1 固定字段

字段名 类型 描述
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 进行扩展。

4.22.2 标签对象示例

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

4.23 引用对象

一个用于在 OpenAPI 描述中引用其他组件的简单对象,支持内部和外部引用。

$ref 字符串值包含一个 URI [RFC3986],用于标识被引用的值。

关于解析 相对引用 的规则,请参见相关说明。

4.23.1 固定字段

字段名 类型 描述
$ref string REQUIRED。引用标识符。此值 MUST 必须为 URI 形式。
summary string 简短摘要,默认情况下 SHOULD 覆盖被引用组件的摘要。如果被引用的对象类型不允许 summary 字段,则此字段无效。
description string 描述,默认情况下 SHOULD 覆盖被引用组件的描述。可以使用 [CommonMark] 语法进行富文本表示(MAY)。如果被引用的对象类型不允许 description 字段,则此字段无效。

此对象不能扩展额外属性,任何被添加的属性 SHALL 被忽略。

注意:对于包含 $ref 关键字的 Schema Objects,与 Reference Objects 在额外属性方面存在差异。

4.23.2 引用对象示例

$ref: '#/components/schemas/Pet'

4.23.3 相对模式文档示例

$ref: Pet.yaml

4.23.4 包含嵌入模式的相对文档示例

$ref: definitions.yaml#/Pet

4.24 Schema 对象

Schema Object 允许定义输入和输出的数据类型。这些类型可以是对象,也可以是原语或数组。该对象是 JSON Schema Specification Draft 2020-12 的超集。空模式(允许任何实例通过验证)MAY 可由布尔值 true 表示,而不允许任何实例通过验证的模式 MAY 可由布尔值 false 表示。

关于关键字的更多信息,请参见 JSON Schema CoreJSON Schema Validation

除非另有说明,关键字定义遵循 JSON Schema 的定义且不添加额外语义;这包括诸如 $schema$id$ref$dynamicRef 等关键字为 URI 而非 URL 的情况。若 JSON Schema 指出某些行为由应用决定(例如注释),OAS 也将语义定义延迟给使用该 OpenAPI 文档的应用。

4.24.1 JSON Schema 关键字

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 中其定义有所扩展:

  • description - 可以使用 [CommonMark] 语法进行富文本表示,MAY 使用。
  • format - 参见 数据类型格式 了解更多细节。在依赖 JSON Schema 已定义格式的同时,OAS 提供了一些额外的预定义格式。

除了组成 OAS 方言的 JSON Schema 关键字外,Schema Object 还支持来自其他词汇表的关键字或任意属性。

JSON Schema 实现 MAY 选择将由 OpenAPI 规范基础词汇定义的关键字视为 未知关键字,因为其在 OAS 方言中以 $vocabulary 值为 false 的方式被包含。 OAS 基础词汇由以下关键字组成:

4.24.2 固定字段

字段名 类型 描述
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- 前缀。

4.24.3 数据类型

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 以数学方式定义整数。这意味着 11.0 在语义上被视为等价,二者都被认为是整数。

4.24.3.1 数据类型格式

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: numbertype: integer 在数据模型中都被视为数字。

4.24.4 解析与序列化

API 数据有几种形式:

  1. 序列化形式:文档(属于某种媒体类型)、HTTP 头值,或 URI 的一部分。
  2. 数据形式:用于配合 Schema Object 的形式。
  3. 应用形式:包含由 JSON Schema 关键字(如 formatcontentType)以及可能的额外信息(例如类层次结构)传达的附加信息。这些超出本规范范围的内容 MAY 基于规范元素(如 Discriminator Object)或关于 数据建模技术 的指引来实现。
4.24.4.1 JSON 数据

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 规范可用。

4.24.4.2 非 JSON 数据

非 JSON 的序列化形式可能与其对应的数据形式有很大不同,且可能需要多个步骤才能解析。

延续我们的 “when” 示例,如果我们将对象序列化为 application/x-www-form-urlencoded,它将以 ASCII 字符串的形式出现:when=1985-04-12T23%3A20%3A50.52。该示例仍然易于使用,因为都是字符串数据,且与 JSON 的唯一区别是 URI 百分号编码和分隔语法(使用 = 替代 JSON 标点和引号)。

然而,许多非 JSON 的文本格式可能很复杂,必须检查相应的模式以将文本正确解析为可供模式使用的数据结构。将数据序列化为此类格式需要检查经过模式验证的数据,或执行相同的模式检查。

在检查模式时,给定一个起始模式,实施者 MUST 检查该模式以及通过仅跟随 $refallOf 关键字可到达的所有模式。这些模式保证适用于任何实例。在搜索模式以查找 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/codecode 属性的起始模式)
  • #/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/countcount 属性的起始模式,发现 type: integer
  • #/components/schemas/FormData/properties/extraextra 属性的起始模式,发现 type: object

注意对 code 我们起初找到一个模糊的 type,但随后又找到了另一个 type 关键字,使两种可能性中只有一种有效。

通过这种检查,我们确定 code 是一个看起来像数字的字符串,而 count 需要在模式验证之前被解析为数字。此外,extra 字符串实际上是一个表示含有 info 属性的对象的 XML 序列化。这意味着该序列化的数据形式等价于下面的 JSON 对象:

{
  "code": "1234",
  "count": 42
  "extra": {
    "info": "abc"
  }
}

序列化该对象还需要将属性与 Encoding Objects 关联,并可能需要检查以确定 contentType 字段的默认值。如果无法获取到已验证的数据,则模式检查过程与解析时相同。

在该示例中,codecount 都是原始类型,且未出现在 encoding 字段中,因此按纯文本序列化。然而,extra 字段是一个对象,默认会被序列化为 JSON,但 encoding 字段中对 extra 的条目告知要改为以 XML 形式序列化。

4.24.4.3 处理二进制数据

OAS 可描述 原始编码 的二进制数据。

  • 原始二进制(raw binary):用于允许未编码的二进制数据场景,例如将二进制有效负载作为整个 HTTP 消息体发送,或作为允许二进制部分的 multipart/* 有效负载的一部分。
  • 编码二进制(encoded binary):用于二进制数据嵌入到仅文本格式中,例如 application/jsonapplication/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 或类似编码。

使用 contentEncodingbase64url 可确保在查询字符串和类型为 application/x-www-form-urlencoded 的消息体中所需的 URL 编码不需对已编码的二进制数据再做额外编码。

若媒体类型已设置,则 contentMediaType 关键字是冗余的,具体场景包括:

如果 Schema Object 将由非 OAS 感知的 JSON Schema 实现处理,即便冗余也可能有用以包含 contentMediaType。但若 contentMediaType 与相关的 Media Type Object 或 Encoding Object 冲突,则 contentMediaType SHALL 被忽略。

有关流式二进制有效负载的指导,请参见 完整内容 与 流式内容

4.24.4.3.1 模式评估与二进制数据

较少的 JSON Schema 实现直接支持处理二进制数据,因为这不是该规范的强制部分。

无法获得支持二进制实例的 JSON Schema 实现的 OAS 实现 MUST 按照 处理二进制数据 一节的要求检查并应用模式。当整个实例为二进制时,因相关关键字较少,处理较为直接。

然而,multipart 媒体类型可以混合二进制和文本数据,使实现对于模式评估有两种选择:

  1. 使用占位值,假定没有断言适用于二进制数据且没有条件模式关键字导致模式对占位值的不同处理(例如,某一部分可能是纯文本或二进制,如果用字符串作为二进制占位值,可能会被视为纯文本并受到不同子模式和关键字的影响)。
  2. 检查模式以找到适当的关键字(如 propertiesprefixItems 等),以便拆分子模式并分别将它们应用到二进制和与 JSON 兼容的数据。
4.24.4.3.2 从 OAS 3.0 迁移二进制描述

下面的表展示了如何从 OAS 3.0 的二进制数据描述迁移(继续以 image/png 为示例二进制媒体类型):

OAS < 3.1 OAS >= 3.1 备注
type: string
format: binary
contentMediaType: image/png 若冗余可省略,通常会导致一个空的 Schema Object
type: string
format: byte
type: string
contentMediaType: image/png
contentEncoding: base64
注意可以使用 base64url 以避免将 base64 字符串重新编码为 URL 安全形式

4.24.5 使用注释的扩展验证

JSON Schema Draft 2020-12 支持 收集注释,包括将未识别的关键字视为注释的处理(见 相关说明)。OAS 实现 MAY 使用这些注释(包括未被声明的 JSON Schema 词汇表识别的 扩展)作为进一步验证的基础。注意 JSON Schema Draft 2020-12 并不要求扩展使用 x- 前缀。

4.24.5.1 非验证性约束关键字

当使用默认的 format-annotation 词汇表时,format 关键字,以及 contentMediaTypecontentEncodingcontentSchema 关键字对数据定义约束,但被视为注释而非直接验证。扩展验证是强制执行这些约束的一种方式,且这些约束 MAY 被这样执行。

4.24.5.2 readOnlywriteOnly 的验证

readOnlywriteOnly 关键字是注释,因为 JSON Schema 无法知道它正在验证的数据将如何被使用。对这些关键字的验证 MAY 通过检查注释、读/写方向以及(若相关)字段的当前值来完成。JSON Schema Validation Draft 2020-12 第 9.4 节 定义了这些关键字的期望行为,包括资源(称为“拥有权威”) MAY 忽略 readOnly 字段或将其视为错误。

同时为必需且只读的字段是一个示例,说明在 PUT 请求中忽略 readOnly: true 约束可能是有益的,特别是在值未被更改的情况下。这允许在 GET 时正确要求该字段,同时仍然在 PUT 时使用相同的表示与模式。即便只读字段不是必需的,移除它们对客户端来说也是繁重的,尤其当 JSON 数据复杂或深度嵌套时。

注意 readOnly 的行为与本规范的 3.0 版本存在差异。

4.24.6 数据建模技术

4.24.6.1 组合与继承(多态)

OpenAPI 规范允许使用 JSON Schema 的 allOf 关键字来组合和扩展模型定义,从而实现模型组合。allOf 接受一组对象定义的数组,这些定义独立验证,但一起组成单个对象。

尽管组合提供了模型的可扩展性,但并不意味着模型之间存在继承层次结构。

JSON Schema 还提供 anyOfoneOf 关键字,分别允许定义多个模式,其中至少一个或恰好一个必须有效。与 allOf 相同,这些模式也是独立验证的。这些关键字可用于描述多态,在该场景中单个字段可以接受多种类型的值。

OpenAPI 规范通过添加 discriminator 字段(其值为 Discriminator Object)扩展了 JSON Schema 对多态的支持。使用时,Discriminator Object 指示用于提示哪个 anyOfoneOf 模式应验证模型结构的属性名称。判定属性 MAY 被定义为必需或可选,但若将其定义为可选,则 Discriminator Object MUST 包含 defaultMapping 字段,以指定在判定属性不存在时期望使用哪个 anyOfoneOf 中的模式,或在 allOf 中引用当前模式的哪个模式。

定义继承实例的判定属性值有两种方式:

  • 使用模式名称。
  • 通过覆盖属性值 来覆盖模式名称。如果存在新的值,则优先于模式名称。
4.24.6.2 通用(模板)数据结构

实现 SHOULD 支持使用 JSON Schema 的动态引用功能来定义通用或模板数据结构:

  • $dynamicAnchor 标识一组可能的模式(包括默认的占位模式),$dynamicRef 可解析到这些模式之一。
  • $dynamicRef 按 JSON Schema 规范,从模式入口点到引用路径上遇到的第一个匹配 $dynamicAnchor 进行解析。

示例包含在下方的 Schema Object 示例 部分,并且在 Learn OpenAPI 网站的 “动态引用” 页面上有更多信息。

4.24.6.3 带注释的枚举

Schema Object 的 enum 关键字不允许为各个值关联描述或其它信息。

实现 MAY 支持识别一种模式:将 oneOfanyOf 中的每个子模式写为包含 const 关键字及诸如 titledescription 等注释,从而作为带有附加信息的枚举类型。此模式在 JSON Schema 所要求行为之外的具体行为由实现定义。

4.24.6.4 XML 建模

xml 字段在将 JSON 定义转换为 XML 时允许额外定义。XML Object 包含有关可用选项的更多信息。

4.24.7 指定模式方言

工具需要能够确定任一资源希望使用哪个方言或元模式进行处理: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 设置方言。

4.24.8 Schema 对象示例

4.24.8.1 原始示例
type: string
format: email
4.24.8.2 简单模型
type: object
required:
  - name
properties:
  name:
    type: string
  address:
    $ref: '#/components/schemas/Address'
  age:
    type: integer
    format: int32
    minimum: 0
4.24.8.3 带映射/字典属性的模型

用于简单的字符串到字符串的映射:

type: object
additionalProperties:
  type: string

用于字符串到模型的映射:

type: object
additionalProperties:
  $ref: '#/components/schemas/ComplexModel'
4.24.8.4 带注释枚举的模型
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
4.24.8.5 带示例的模型
type: object
properties:
  id:
    type: integer
    format: int64
  name:
    type: string
required:
  - name
examples:
  - name: Puma
    id: 1
4.24.8.6 具有组合的模型
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
4.24.8.7 支持多态的模型

下面示例描述了一个 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
4.24.8.8 带 Discriminator Object 的多态模型示例

下面的示例在上一节示例的基础上,为 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
4.24.8.9 使用 allOf 与 Discriminator Object 的多态模型示例

也可以使用 allOf 描述多态模型。以下示例使用 allOfDiscriminator 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
4.24.8.10 通用数据结构模型
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

4.25 判别器对象

当请求体或响应负载可能属于多种不同模式之一时,应使用 JSON Schema 的 anyOfoneOf 关键字来描述可能的模式(见 组合与继承)。

多态模式 MAY 包含一个判别器(Discriminator Object),用于定义可作为提示的属性名称,该属性可指示在 anyOfoneOf 中哪个模式,或在 allOf 中引用当前模式的哪个模式,预期用于验证模型结构。该提示可以用于帮助序列化、反序列化和验证。判别器对象通过隐式或显式地将命名属性的可能值与替代模式关联来实现此目的。

注意 discriminator MUST NOT 改变模式的验证结果。

4.25.1 固定字段

Field Name Type Description
propertyName string REQUIRED。载荷中用于保存判别值的判定属性的名称。判定属性 MAY 被定义为必需或可选,但当定义为可选时,判别器对象 MUST 包含一个 defaultMapping 字段,该字段指定在判定属性不存在时代码期望用于验证模型结构的模式。
mapping Map[string, string] 用于保存载荷值与模式名称或 URI 引用之间映射的对象。
defaultMapping string 当载荷中未包含判定属性或判定属性包含没有显式或隐式映射的值时,预期用于验证模型结构的模式名称或模式的 URI 引用。

此对象 MAY 使用 Specification Extensions 进行扩展。

4.25.2 使用判别器对象的条件

只有在使用复合关键字之一 oneOfanyOfallOf 时,判别器对象才是合法的。

oneOfanyOf 的用例中,当这些关键字与 discriminator 并列时,所有可能的模式 MUST 被显式列出。

为避免冗余,判别器 MAY 被添加到父模式定义中,通过 allOf 构建在该父模式之上的所有模式都可以作为备选模式使用。

allOf 形式的 discriminator 仅对非验证用途有用;使用该形式的 discriminator 与父模式一起进行验证时,不会 搜索子模式或以任何方式在验证中使用它们。这是因为 discriminator 无法改变验证结果,并且没有标准的 JSON Schema 关键字将父模式与子模式连接起来。

任何未在上述描述中的 oneOfanyOfallOfdiscriminator 的配置的行为均未定义。

4.25.3 将值映射到模式的选项

propertyName 指定的属性的值被用作在 Components Object 下关联模式的名称,除非该值存在对应的 mappingmapping 条目将特定的属性值映射到不同的模式组件名称或由 URI 标识的模式。当使用隐式或显式的模式组件名称时,内联的 oneOfanyOf 子模式不予考虑。若某个 mapping 值或 defaultMapping 值同时是有效的模式名称和有效的相对 URI 引用,则其行为由实现定义,但建议(RECOMMENDED)将其视为模式名称。为确保歧义值(例如 "foo")被所有实现视为相对 URI 引用,作者 MUST 在其前面加上路径段 "."(例如 "./foo")。

映射键 MUST 为字符串值,但工具链 MAY 将响应值转换为字符串以便比较。然而,此类转换的具体性质由实现定义。

4.25.4 可选的判定属性

当判定属性被定义为可选时,判别器对象 MUST 包含一个 defaultMapping 字段,指定在载荷中判定属性不存在或包含没有显式或隐式映射值时,预期用于验证模型结构的模式。这样即使缺少判定属性,模式仍能被正确验证。

可选判定属性的主要用途是允许在不破坏未提供判定属性的现有客户端的情况下向模式添加判别器。

当判定属性被定义为可选时,每个在子模式中定义了该判定属性值的子模式也应将该属性定义为必需,因为父模式不再强制执行此项。

defaultMapping 模式也应在判定属性存在但其值没有显式或隐式映射时,能用于验证模型结构。通常在 defaultMapping 模式中通过排除任何具有映射判定值的实例来表达,例如:

OtherPet:
  type: object
  properties:
    petType:
      not:
        enum: ['cat', 'dog']

这可以防止 defaultMapping 模式验证包含已映射判定值的载荷,否则使用 oneOf 描述多态时会导致验证失败。

4.25.5 示例

在这些示例中,假设所有模式都位于 OAD 的 入口文档;关于在被引用文档中处理 discriminator 的说明,请参见 解析隐式连接

在 OAS 3.x 中,响应负载 MAY 被描述为恰好为任意数量类型之一:

MyResponseType:
  oneOf:
    - $ref: '#/components/schemas/Cat'
    - $ref: '#/components/schemas/Dog'
    - $ref: '#/components/schemas/Lizard'

这意味着有效载荷必须恰好匹配由 CatDogLizard 描述的其中一个模式。对 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 字段,指定在载荷中判定属性不存在时代码期望用于验证模型结构的 anyOfoneOf 中的某个模式。这样即使缺少判定属性,模式仍能被正确验证。

例如:

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)。

4.26 XML 对象

一个元数据对象,用于更细粒度地定义 XML 模型。当在 Schema Object 中使用 XML 时,如果没有提供 XML Object,则行为由 XML Object 的默认字段值决定。

4.26.1 固定字段

Field Name Type Description
nodeType string 取值为 elementattributetextcdatanone 之一,详见 XML 节点类型。当包含该 XML Object 的 Schema Object 中存在 $ref$dynamicReftype: "array" 时,默认值为 none,否则为 element
name string 设置与该模式对应的元素/属性名称,替换在 XML 节点名称 中说明的推断名称。当 nodeTypetextcdatanone 时,该字段 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 进行扩展。

4.26.2 XML 节点类型

每个 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 的为便于重用而存在的模式)很有用。

4.26.2.1 建模元素列表

为兼容历史,type: "array" 的模式默认 nodeType: "none",将每个数组项的节点放在父节点下。这也与 XML 节点名称 中定义的推断命名行为一致。

要生成包含列表的元素,请在 type: "array" 模式上显式设置 nodeType: "element"。在此情况下,建议对包裹元素或项元素之一设置显式名称,以避免它们具有相同的推断名称。请参见示例以了解预期行为。

4.26.2.2 隐式与显式 text 节点

如果某个 element 节点具有原始类型,则该模式还会为该 element 节点的内容生成一个由该元素内容的模式描述的隐式 text 节点,名称为属性名(或 name 字段)。

如果一个元素同时具有属性与内容,则需要显式的 text 节点。

注意,将两个 text 节点相邻放置对解析来说是歧义的,其结果行为由实现定义。

4.26.3 XML 节点名称

elementattribute 节点类型需要名称,该名称 MUST 按照如下方式从模式中推断,除非被 name 字段覆盖:

  • 对于直接位于 Components Objectschemas 字段下的模式,组件名称为推断名称。
  • 对于属性模式,以及属性模式下数组项的模式,属性名称为推断名称。
  • 在所有其它情况下,例如在 Media Type Objectschema 字段下的内联模式,无法推断名称,因此必须存在带有 name 字段的 XML Object。

注意:在使用数组时,不会推断单数或复数形式,必须显式设置。

4.26.4 命名空间限制

namespace 字段旨在匹配 XML 命名空间的语法(参见 XML namespaces),但有几点注意事项:

  • 规范的 3.1.0、3.0.3 及更早版本错误地使用了“absolute URI”而非“non-relative URI”(在 OAS v3.2.0 中为“non-relative IRI”)这一术语,因此使用包含片段的命名空间的作者应谨慎检查工具支持情况。
  • XML 允许但不鼓励相对 IRI 引用,而本规范则明确禁止相对 IRI。

4.26.5 处理 null

XML 默认情况下没有等价于 null 的概念,为了与本规范 3.1.1 及更早版本兼容,序列化 null 值的行为由实现定义。

然而,实现 SHOULD 按如下方式处理 null 值:

  • 对于元素,生成带有 xsi:nil="true" 属性的空元素。
  • 对于属性,省略该属性。
  • 对于文本和 CDATA 节,请参见 附录 B,了解将非文本值序列化为文本的讨论。

注意:对于属性,这意味着 null 值或缺失属性都会序列化为省略的属性。由于 Schema Object 验证的是内存表示,这允许处理 null 与必需属性的组合。然而,因为无法以不同方式将 null 表示为属性,建议(RECOMMENDED)将属性类型设为可选而非使用 null

为确保正确的往返行为,在解析省略了属性的元素时,如果模式允许该值(例如 type: ["number", "null"]),实现 SHOULD 将对应属性设置为 null,否则应省略该属性(例如 type: "number")。

4.26.6 XML 对象示例

下面在每个模式后给出一个为该模式生成的示例 XML 表示。有关使用 attributewrapped 的示例,请参见 OpenAPI Specification 3.1。

4.26.6.1 无 XML Object

基本字符串属性没有 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>

基本字符串数组属性(默认 nodeTypenone):

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>
4.26.6.2 XML 名称替换
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>
4.26.6.3 XML 属性、前缀与命名空间

注意根 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>
4.26.6.4 XML 数组

更改元素名称示例:

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 字段无效,因为该对象的默认 nodeTypenone

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>
4.26.6.5 带属性与文本的元素
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>
4.26.6.6 引用的带 CDATA 的元素

在此示例中,仅包含 $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>
4.26.6.7 有序元素与文本

要控制元素的确切顺序,请使用 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>
4.26.6.8 null 值的 XML

请记住,模式验证的是内存数据,而不是 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>

4.27 安全方案对象

定义可被操作使用的安全方案。

支持的方案包括 HTTP 验证、API 密钥(作为头部、cookie 参数或查询参数)、双向 TLS(使用客户端证书)、OAuth2 的常见流程(隐式、密码、客户端凭证和授权代码),如 [RFC6749] 所定义;OAuth2 设备授权流程,如 [RFC8628] 所定义;以及 [OpenID-Connect-Core]。请注意,截至 2020 年,隐式流程已由 OAuth 2.0 Security Best Current Practice 建议弃用。对于大多数使用场景,推荐使用带 PKCE 的授权代码授权(Authorization Code Grant)流程。

4.27.1 固定字段

字段名 类型 适用对象 描述
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 使用 规范扩展 进行扩展。

4.27.2 安全方案对象示例

4.27.2.1 基本认证示例
type: http
scheme: basic
4.27.2.2 API 密钥示例
type: apiKey
name: api-key
in: header
4.27.2.3 JWT 承载示例
type: http
scheme: bearer
bearerFormat: JWT
4.27.2.4 双向 TLS 示例
type: mutualTLS
description: Cert must be signed by example.com CA
4.27.2.5 隐式 OAuth2 示例
type: oauth2
flows:
  implicit:
    authorizationUrl: https://example.com/api/oauth/dialog
    scopes:
      write:pets: modify pets in your account
      read:pets: read your pets

4.28 OAuth 流程对象

允许配置所支持的 OAuth 流程。

4.28.1 固定字段

字段名 类型 描述
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 使用 规范扩展 进行扩展。

4.29 OAuth 流对象

受支持的 OAuth 流的配置详情

4.29.1 固定字段

字段名 类型 适用对象 描述
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 进行扩展。

4.29.2 OAuth 流对象示例

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: 读取您的宠物

4.30 安全需求对象

列出执行此操作所需的安全方案。

用于每个属性的名称 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 ObjectOperation Object 上定义 security 字段并包含多个 Security Requirement Objects 时,列表中的任意一项满足即可授权请求。这支持 API 允许多种独立安全方案的场景。

空的 Security Requirement Object({})表示支持匿名访问。

4.30.1 模式字段

字段模式 类型 描述
{name} [string] 每个名称或 URI MUST 对应上述描述的安全方案。如果安全方案类型为 "oauth2""openIdConnect",则其值为执行所需的 scope 名称列表;若授权不要求指定 scope,则该列表 MAY 为空。对于其它安全方案类型,数组 MAY 包含执行所需的角色名称,但这些角色名称不会在带内定义或交换。

4.30.2 安全需求对象示例

另见 隐式连接解析示例(位于 附录 G:解析与解析指导),其中展示了在多文档 OpenAPI 描述中使用 Security Requirement Objects 的示例。

4.30.2.1 非 OAuth2 的安全需求
api_key: []
4.30.2.2 OAuth2 安全需求

此示例使用 Security Scheme 的组件名称。

petstore_auth:
  - write:pets
  - read:pets
4.30.2.3 可选的 OAuth2 安全

此示例使用 Security Scheme 的相对 URI 引用。

OpenAPI ObjectOperation Object 中定义的可选 OAuth2 安全示例如下:

security:
  - {}
  - petstore_auth:
      - write:pets
      - read:pets

5. 规范扩展

尽管 OpenAPI 规范试图涵盖大多数用例,但可以在某些点添加额外数据以扩展规范。

扩展属性以模式化字段实现,始终以 x- 为前缀。

字段模式 类型 描述
^x- Any 允许对 OpenAPI 模式进行扩展。字段名 MUSTx- 开头,例如 x-internal-id。以 x-oai-x-oas- 开头的字段名保留供 OpenAPI Initiative 定义的用途使用。值可以是任何有效的 JSON 值(null、原语、数组或对象)。

OpenAPI Initiative 维护多个 扩展注册表,包括针对 单个扩展关键字扩展关键字命名空间 的注册表。

扩展是验证拟议添加项可行性的最佳方式之一。因此 RECOMMENDED 实现应被设计为可扩展以支持社区实验。

对任一扩展的支持为 OPTIONAL,对一个扩展的支持并不意味着对其他扩展的支持。

6. 安全注意事项

6.1 OpenAPI 描述格式

OpenAPI 描述使用 JSON、YAML 和 JSON Schema 的组合,因此它们共享相应的安全注意事项:

6.2 工具与使用场景

此外,OpenAPI 描述会被各种工具以多种用途处理,例如客户端代码生成、文档生成、服务端路由和 API 测试。OpenAPI 描述作者必须考虑 OpenAPI 描述可能被使用的场景所带来的风险。

6.3 安全方案

OpenAPI 描述说明了用于保护其定义资源的安全方案。可用的安全方案提供不同程度的保护。数据的敏感性和安全漏洞可能带来的影响等因素应指导 API 资源安全方案的选择。有些安全方案(例如 basic auth 和 OAuth 隐式流程)是为与现有 API 兼容而支持的。然而,在 OpenAPI 中包含它们并不意味着对其使用的认可,尤其是在处理高度敏感的数据或操作时。

Security Requirement Object 连接到 Security Scheme Object(位于 Components Object 下)时的规则存在模糊之处,可能被利用。具体而言:

6.4 安全过滤

OpenAPI 规范中的某些对象 MAY 被声明但保持为空,或被完全移除,尽管它们本质上是 API 文档的核心。

其原因是允许在文档之上增加一层访问控制。尽管这不是规范本身的一部分,但某些库 MAY 选择基于某种形式的认证/授权来允许访问文档的部分内容。

两个例子:

  1. Paths Object MAY 存在但为空。虽然这可能令人困惑,但这可能告诉查看者他们来到了正确的位置,但无法访问任何文档。查看者仍然至少可以访问 Info Object,其中可能包含关于认证的额外信息。
  2. Path Item Object MAY 为空。在这种情况下,查看者会知道该路径存在,但无法查看其任何操作或参数。这与将路径本身从 Paths Object 中隐藏不同,因为用户仍会知道其存在。这允许文档提供者精细控制查看者能看到的内容。

6.5 处理外部资源

OpenAPI 描述可能包含对外部资源的引用,消费工具可能会自动对其进行解引用。外部资源可能托管在不同且不受信任的域上。

6.6 处理引用循环

OpenAPI 描述中的引用可能导致循环。工具必须检测并处理循环以防止资源耗尽。

6.7 Markdown 与 HTML 清理

某些字段允许使用 Markdown,而 Markdown 可能包含包括脚本在内的 HTML。适当清理 Markdown(sanitization)是工具的责任。

A. 附录 A:修订历史

版本 日期 说明
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 规范

B. 附录 B:数据类型转换

将类型化数据序列化为纯文本(例如在 text/plain 消息体或 multipart 部分中,或在 URL 查询字符串或消息体中的 application/x-www-form-urlencoded 格式中)涉及大量由实现或应用定义的行为。

Schema Objects 基于 JSON Schema 数据模型 对数据进行验证,该模型仅识别四种原始数据类型:字符串(通常仅作为 UTF-8 具有良好互操作性)、数字、布尔值和 null。值得注意的是,整数并不是与其它数字不同的独立类型,type: "integer" 只是一个数学上的便利,而不是基于字符串表示中是否包含小数点来区分。

Parameter ObjectHeader ObjectEncoding Object 提供了控制如何排列数组或对象类型值的功能。它们还可以控制如何对字符串进行进一步编码以避免保留或非法字符。然而,对于将经模式验证的非 UTF-8 原始数据类型(或整个数组或对象)转换为字符串,并没有通用规范。

有两种情况提供基于标准的指导:

RFC6570 的实现通常对非字符串值的转换有自己的约定,但这些是实现特定的,不由 RFC 本身定义。这也是 OpenAPI 将这些转换留给实现定义的原因之一:它允许使用任意 RFC6570 实现而无需依赖其具体转换策略。

为了更精确地控制数字、布尔值和 null(或 RFC6570 视为未定义的其他值)的序列化,可以将模式定义为 type: "string" 并使用 patternenumformat 等关键字来约束,以指示应用在模式验证前必须如何预先转换其数据。得到的字符串就不需要进一步的类型转换。

format 关键字可以辅助序列化。一些格式(例如 date-time)是不含歧义的,而有些(例如格式注册表中的 decimal)则不够明确。然而,使用 format 时必须小心,确保相关工具支持特定格式,否则未识别的格式将被忽略。

要求输入为预格式化、模式验证通过的字符串也能改善往返互操作性,因为并非所有编程语言和环境都支持相同的数据类型。

C. 附录 C:使用基于 RFC6570 的序列化

在三种场景中,序列化以 [RFC6570] URI 模板来定义:

对象 条件
Parameter Object 当存在 schema
Header Object 当存在 schema
Encoding Object 当对 application/x-www-form-urlencoded 进行编码并使用任一 styleexplodeallowReserved

本规范的实现 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 模板以规避限制。

C.1 字段与 RFC6570 操作符的等价关系

某些字段值可转换为 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 所处理的单层复合值指定行为。对对象或数组使用在没有明确行为的情况下,其结果由实现定义。

C.2 参数值中的分隔符

RFC6570 展开使用的分隔符(例如用于将数组或对象值与 style: "simple" 一起连接的 ,)在 allowReservedfalse 时会被自动百分号编码。注意由于 RFC6570 并未定义基于 URI 模板解析变量的方法,用户必须先按分隔符拆分值,然后再对可能包含分隔符字符的值进行百分号解码。

allowReservedtrue 时,必须在正确的时机手动执行百分号编码(在连接值之前)和百分号解码(在按分隔符拆分之后)。

关于在没有 RFC6570 等价物的 style 值中处理作为分隔符而需要百分号编码的字符的更多指导,请参见 附录 E

C.3 非 RFC6570 字段值与组合

对没有直接 [RFC6570] 等价物的配置,应该(SHOULD)依照 RFC6570 处理。实现 MAY 使用 RFC6570 的常规或保留扩展(基于 allowReserved)为单独名称和值创建正确分隔的 URI 模板变量以绕过限制。

这包括:

Parameter Object 的 name 字段的语法比 RFC6570 的 变量名语法 要宽松得多。包含 RFC6570 变量字符集之外字符的参数名 MUST 在用于 URI 模板之前进行百分号编码。

C.4 示例

假设我们想在表单查询字符串中使用以下数据,其中 formulas 被展开,而 words 则不被展开:

formulas:
  a: x+y
  b: x/y
  c: x^y
words:
- math
- is
- fun

C.4.1 RFC6570 等价展开

此数组的 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

C.4.2 使用非 RFC6570 支持选项的展开

但现在假设(出于某种原因),我们确实希望 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 获取关于百分号编码与表单媒体类型的更多指导,包括在参数名和值中处理 spaceDelimitedpipeDelimiteddeepObject 分隔符字符的建议。

下面是我们的数据结构,将名称和值安排为适合上述模板,其中 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 被保留,但值中不允许的字符 ^ 和模板中但不在扩展变量内的空格字符被百分号编码。

C.4.3 未定义值与手动构造 URI 模板

在手动构造模板时,必须小心正确处理 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

C.4.4 非法变量名作为参数名

在此示例中,心形表情符号在 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

D. 附录 D:序列化头与 Cookie

HTTP 头在允许哪些字符以及如何对某些或全部不允许字符进行转义并包含方面规则不一致。虽然 [RFC9110] 中给出的 quoted-string ABNF 规则(见 第 5.4.6 节)是最常见的转义方案,但它并不足以普遍适用。例如,强实体标签(strong ETag)看起来像 "foo"(带引号,不论内容如何),而弱实体标签(weak ETag)看起来像 W/"foo"(注意只有部分值被引用);对于该头的引号内容,其转义方式也不同于 quoted-string 内容的转义。

因此,通过 ParameterHeader 对头传递的任何数据,需要在传给 OAS 实现之前先进行引号和转义,并且解析后的头值应包含引号和转义内容。

D.1 百分号编码与 Cookie

RFC6570 的百分号编码行为并不总是适用于 in: "cookie" 参数。虽然与 [RFC6265](及其建议替代草案)推荐的 base64 编码(contentEncoding: “base64”)相比,百分号编码似乎更常见,但 draft-ietf-httpbis-rfc6265bis-20 的第 5.6 节 指出,在 Set-Cookie 响应头中看起来像已被百分号编码的 Cookie,当客户端存储时 MUST NOT 被解码,这意味着它们在从存储中检索用于 Cookie 请求头时已经是编码状态。style: "cookie" 的行为假设了这种用法,并且 应用或移除百分号编码。

如果希望自动进行百分号编码,可对原始值使用 style: "form"(针对原始值)或在非默认 explodefalse 时使用 style: "form"。然而请注意,对于非原始值,style: "form" 的默认 explode: true 会使用错误的分隔符来设置多个 cookie 值(使用 & 而不是应为 ; 后跟一个空格)。使用 RFC6570 实现通过 style: "form"in: "cookie" 时,需要像生成 application/x-www-form-urlencoded 消息体那样去除 ? 前缀。若要充分使用 style: "form"in: "cookie",可使用 allowReserved 字段。

E. 附录 E: 百分号编码与表单媒体类型

注意: 在本节中,为了可读性,application/x-www-form-urlencodedmultipart/form-data 媒体类型分别缩写为 form-urlencodedform-data

百分号编码用于 URI 以及其语法来源于 URI 的媒体类型。 百分号编码的基本规则如下:

本附录其余部分基于上述规则提供更详细的指导。

E.1 百分号编码的字符类

本过程涉及三类字符,这些名称在不同规范中有所不同,但在本节中定义如下:

除非另有说明,本节采用 RFC3986 对 reservedunreserved 的定义,并将不属于这两类的所有字符定义为 unsafe 集合。

E.2 百分号编码与 form-urlencoded

每个 URI 组件(例如查询字符串)将部分保留字符视为不安全,要么因为它们在组件之间作为分隔符(例如 #),要么因为(如 [])历史上被视为全局不安全但后来为有限目的赋予了保留地位。

在某个组件内没有定义特殊含义的保留字符可以保持未百分号编码。然而,其他规范可以为这些字符定义特殊含义,要求在那些特殊含义之外的情形对这些字符进行百分号编码。

form-urlencoded 媒体类型将 =& 定义为分隔符,并将 + 定义为空格的替代表示(而不是其百分号编码形式 %20)。 这意味着虽然这三者在 RFC3986 中作为保留但在查询字符串中被允许,但在 form-urlencoded 查询字符串中,它们必须被百分号编码,除非它们用于 form-urlencoded 的特殊用途;关于在表单值中处理 + 的示例,见 附录 C

E.3 百分号编码与 form-data

[RFC7578] 第 2 节 建议使用基于 RFC3986 的百分号编码作为一种机制,以将诸如文件名等按部分的基于文本的头数据保持在 ASCII 字符集内。 该建议并非旧的(2015 年之前的)form-data 规范的一部分,因此必须小心以确保互操作性。 希望以这种方式使用百分号编码的用户 MUST 以百分号编码的形式提供数据,因为对于该媒体类型,无论使用哪个 Encoding Object 字段,都不会自动应用百分号编码。

form-data 媒体类型允许其各部分包含任意文本或二进制数据,因此通常不需要百分号编码或类似的转义。

E.4 生成与验证 URI 及 form-urlencoded 字符串

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 的带百分号编码的序列化;当至少存在 styleexplodeallowReserved 之一时,Encoding Object 中也使用基于 style 的序列化。 有关 RFC6570 的两种不同百分号编码方法的更多细节以及包含 + 的示例,请参见 附录 C

基于内容的序列化由 Media Type Object 定义,并在 Parameter ObjectHeader Object 中当存在 content 字段时使用;当 styleexplodeallowReserved 字段缺失时,基于 contentType 字段,Encoding Object 也会使用基于内容的序列化。 用于 URI 时,每个部分根据媒体类型进行编码(例如 text/plainapplication/json),随后必须为了在 form-urlencoded 字符串(在表单样式查询字符串中)或在其他 URL 组件用于一般 URI 时进行百分号编码,除非该媒体类型已经包含了 URI 百分号编码。

E.4.1 与历史规范的互操作性

本规范的先前版本要求使用 [RFC1866] 及其对 [RFC1738] 的百分号编码规则,而不是使用 [WHATWG-URL]。 [WHATWG-URL] 的 form-urlencoded 规则代表了当前浏览器社区在该媒体类型上的共识,并避免了 RFC1866 中对 RFC1738 不清晰释述所引入的歧义。

需要与 RFC1866/RFC1738 保持一致性的用户应仔细检查其工具和库的行为。

E.4.2 与 Web 浏览器环境的互操作性

WHATWG 是一个面向 Web 浏览器 的标准组织,它为浏览器上下文中的 URL 解析和序列化定义了“URL 活动标准”,包括 form-urlencoded 数据的解析与序列化。 WHATWG 关于查询字符串的百分号编码规则会根据查询字符串是否被视为 作为 form-urlencoded(在该情形下它要求比 [RFC1738] 更多的百分号编码)或作为通用语法的一部分(其要求与 [RFC3986] 不同)而有所不同。

本规范仅在 form-urlencoded 规范方面依赖 WHATWG。那些以其他方式使用查询字符串的实现应意识到,WHATWG 关于非 form-urlencoded 查询字符串规则与 RFC3986 之间的区别需要谨慎考虑,结合 WHATWG 的百分号编码集合及其对 URL 的有效 Unicode 代码点集合;详见 关于百分号编码和非法或保留分隔符

E.5 解码 URI 与 form-urlencoded 字符串

百分号解码算法并不关心哪些字符曾被或未被百分号编码,这意味着按照任一规范进行百分号编码的 URI 都能被正确解码。

同样地,所有 form-urlencoded 解码算法只是对百分号解码算法添加了 +-表示空格的处理,因此无论采用哪种编码规范,解码都能工作。

然而,需要注意:如果 + 表示空格,则必须使用 form-urlencoded 解码;如果 + 本身表示字面值,则应使用常规的百分号解码。

E.6 百分号编码与非法或保留分隔符

用于 deepObjectpipeDelimitedspaceDelimited 样式的分隔符字符 []| 和空格,均 MUST 被百分号编码以符合 [RFC3986] 的要求。 这要求用户在参数名称和值中以某种方式预先对这些字符进行编码,以便在使用这些样式时将它们与分隔符用途区分开来。

空格字符在所有相关标准的所有实现中始终是非法的,并且以某种方式被编码。 虽然可以使用 form-urlencoded 约定的 + 来将参数名称和值中的空格与作为分隔符的 spaceDelimited(其编码为 %20)区分开,但规范将解码定义为单次处理,使得在解码后的结果中无法区分不同用法,除非使用先基于一种分隔符分割再解码另一种分隔符的非标准解析算法。任何此类非标准解析方法都不会在所有工具间互操作。

某些环境在查询字符串中使用未编码的 [],甚至可能使用 |,且似乎没有出现问题。WHATWG 的通用查询字符串规则在非 form-urlencoded 的查询字符串中不要求对它们进行百分号编码,尽管它也将它们排除在 URL 的有效 Unicode 代码点集合之外。 依赖在名称和值中对这些分隔符保持未编码但在其它位置使用常规百分号编码的代码,不能保证在所有实现间互操作。

为获得最大互操作性,RECOMMENDED 的做法是:在对这些样式的分隔符进行百分号编码的同时,定义并记录一个额外的转义约定,或完全避免使用这些样式。 额外编码/转义的具体方法由 API 设计者决定,预期在本规范描述的序列化和编码步骤之前执行该预处理,并在对这些步骤反向处理时再将其还原。 这样可以将其保持在本规范所管理流程之外。

F. 附录 F:基本 URI 确定与引用解析示例

本节展示四种可能的基本 URI 来源中的每一种,随后举例说明带相对 $self$id 的情况。

F.1 内容内的基本 URI

资源内容内的基本 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。

F.2 来自封装实体的基本 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

F.3 来自检索 URI 的基本 URI

如果前两种来源都未提供基本 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。

F.4 应用特定的默认基本 URI

当在内存中构建的 OpenAPI 文档既没有 $self、也没有封装实体或检索 URI 时,应用可以通过假定一个默认基本 URI 来解析内部(仅片段)引用(参见 [RFC3986] 第 5.1.4 节)。 虽然此类内部解析在实践中可以在不选择基本 URI 的情况下执行,但选择一个(例如带随机生成 UUID 的 URN,如 urn:uuid:f26cdaad-3193-4398-a838-4ecb7326c4c5)可以避免将其作为特殊情况来实现。

F.5 解析相对的 $self$id

让我们重新考虑本附录的第一个示例,但将 $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,从而第一个文档的 $selfhttps://staging.example.com/openapi,第二个文档的 $selfhttps://staging.example.com/api/shared/foo,相应的 $id 值为 https://staging.example.com/api/schemas/foohttps://staging.example.com/api/schemas/bar。 此类相对的 $self$id 值使得同一组文档在部署到其他主机时也能工作,例如生产环境的 https://example.com 或本地开发的 https://localhost:8080

G. 附录 G:解析与解析指导

实现 MAY 支持以下任一方式的完整文档解析:

还可以使用额外机制来支持根节点为 OpenAPI Object 或 Schema Object 之外的对象的文档,但请注意其结果行为由实现定义:

G.1 关于片段解析的警告

在不考虑包含文档其余内容的情况下解析被引用的 OpenAPI 片段的实现,会错过可能改变引用目标含义和行为的关键字。 特别地,未考虑那些改变基本 URI 的关键字会引入安全风险,因为这会导致引用解析到非预期的 URI,产生不可预测的结果。 虽然一些实现因过去规范的要求而支持这种解析方式,但在 3.1 及以后的版本中,孤立片段解析的结果是 未定义 的,并且很可能与本规范的要求相冲突。

虽然可以构造某些 OpenAPI 描述以确保在将引用作为孤立片段解析时仍能正确工作,但依赖此行为 NOT RECOMMENDED。 本规范未明确列出在何种条件下此类行为是安全的,并且不保证在任何未来版本的 OAS 中继续保持安全。

G.2 字段类型与引用上下文之间的冲突

OAD 中的 JSON 或 YAML 对象根据其上下文被解释为特定的对象类型(例如 Operation ObjectsResponse ObjectsReference Objects 等)。取决于引用的安排,给定的 JSON 或 YAML 对象可能在多种不同上下文中被解释:

如果相同的 JSON/YAML 对象被多次解析且各自上下文要求其被解析为不同的对象类型,则其结果行为为 实现定义,并且如果检测到可被视为错误(MAY)。例如,在期望 Path Item Object 的位置下引用位于 #/components/schemas 的空 Schema Object,因为空对象对两种类型都是有效的。为获得最大互操作性,RECOMMENDED OpenAPI 描述作者避免此类情形。

G.3 关于隐式连接的指导

下列对象和字段涉及隐式连接的使用:

来源 目标 替代
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 Objecttags 数组中) n/a
Link Object operationId Operation Object operationId operationRef

另一个隐式连接涉及将 Paths Object 的模板化 URL 路径附加到相应 Server Objecturl 字段。 该连接无歧义,因为只有入口文档的 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

G.3.1 隐式连接解析示例

本节展示如何检索一个可通过 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 的解析具有实现定义的行为,但该节正式建议工具应从 入口文档 解析组件名称。与所有实现定义的行为一样,重要的是检查工具文档以确定支持哪种行为。

H. 参考文献

H.1 规范性参考文献

[ABNF]
语法规范的扩展 BNF:ABNF。D. Crocker,编;P. Overell。IETF。2008 年 1 月。互联网标准。URL: https://www.rfc-editor.org/rfc/rfc5234
[CommonMark]
CommonMark 规范。URL: https://spec.commonmark.org/
[CommonMark-0.27]
CommonMark 规范,版本 0.27。John MacFarlane。2016 年 11 月 18 日。URL: https://spec.commonmark.org/0.27/
[DOM]
DOM 标准。Anne van Kesteren。WHATWG。 活动标准。URL: https://dom.spec.whatwg.org/
[IANA-HTTP-AUTHSCHEMES]
超文本传输协议 (HTTP) 认证方案注册表。IANA。URL: https://www.iana.org/assignments/http-authschemes/
[IANA-HTTP-STATUS-CODES]
超文本传输协议 (HTTP) 状态代码注册表。IANA。URL: https://www.iana.org/assignments/http-status-codes/
[OpenAPI-Registry]
OpenAPI Initiative 注册表。OpenAPI Initiative。URL: https://spec.openapis.org/registry/index.html
[OpenID-Connect-Core]
OpenID Connect Core 1.0(含勘误集 2)。N. Sakimura;J. Bradley;M. Jones;B. de Medeiros;C. Mortimore。OpenID Foundation。2023 年 12 月 15 日。最终。URL: https://openid.net/specs/openid-connect-core-1_0.html
[OpenID-Connect-Discovery]
OpenID Connect Discovery 1.0(含勘误集 2)。N. Sakimura;J. Bradley;M. Jones;E. Jay。OpenID Foundation。2023 年 12 月 15 日。最终。URL: https://openid.net/specs/openid-connect-discovery-1_0.html
[RFC2046]
多用途 Internet 邮件扩展 (MIME) 第二部分:媒体类型。N. Freed;N. Borenstein。IETF。1996 年 11 月。草案标准。URL: https://www.rfc-editor.org/rfc/rfc2046
[RFC2119]
在 RFC 中用于指示要求级别的关键字。S. Bradner。IETF。1997 年 3 月。最佳当前实践。URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC3986]
统一资源标识符 (URI):通用语法。T. Berners-Lee;R. Fielding;L. Masinter。IETF。2005 年 1 月。互联网标准。URL: https://www.rfc-editor.org/rfc/rfc3986
[RFC3987]
国际化资源标识符 (IRIs)。M. Duerst;M. Suignard。IETF。2005 年 1 月。建议标准。URL: https://www.rfc-editor.org/rfc/rfc3987
[RFC4648]
Base16、Base32 与 Base64 数据编码。S. Josefsson。IETF。2006 年 10 月。建议标准。URL: https://www.rfc-editor.org/rfc/rfc4648
[RFC6265]
HTTP 状态管理机制。A. Barth。IETF。2011 年 4 月。建议标准。URL: https://httpwg.org/specs/rfc6265.html
[RFC6570]
URI 模板。J. Gregorio;R. Fielding;M. Hadley;M. Nottingham;D. Orchard。IETF。2012 年 3 月。建议标准。URL: https://www.rfc-editor.org/rfc/rfc6570
[RFC6749]
OAuth 2.0 授权框架。D. Hardt,编。IETF。2012 年 10 月。建议标准。URL: https://www.rfc-editor.org/rfc/rfc6749
[RFC6901]
JSON 指针(JavaScript Object Notation Pointer)。P. Bryan,编;K. Zyp;M. Nottingham,编。IETF。2013 年 4 月。建议标准。URL: https://www.rfc-editor.org/rfc/rfc6901
[RFC7578]
从表单返回值:multipart/form-data。L. Masinter。IETF。2015 年 7 月。建议标准。URL: https://www.rfc-editor.org/rfc/rfc7578
[RFC8174]
RFC 2119 关键字大小写歧义。B. Leiba。IETF。2017 年 5 月。最佳当前实践。URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC8259]
JSON(JavaScript Object Notation)数据交换格式。T. Bray,编。IETF。2017 年 12 月。互联网标准。URL: https://www.rfc-editor.org/rfc/rfc8259
[RFC8414]
OAuth 2.0 授权服务器元数据。M. Jones;N. Sakimura;J. Bradley。IETF。2018 年 6 月。建议标准。 URL: https://www.rfc-editor.org/rfc/rfc8414
[RFC8628]
OAuth 2.0 设备授权授予。W. Denniss;J. Bradley;M. Jones;H. Tschofenig。IETF。2019 年 8 月。建议标准。URL: https://www.rfc-editor.org/rfc/rfc8628
[RFC9110]
HTTP 语义。R. Fielding,编; M. Nottingham,编;J. Reschke,编。IETF。2022 年 6 月。互联网标准。URL: https://httpwg.org/specs/rfc9110.html
[RFC9264]
Linkset:链接集的媒体类型与链接关系类型。E. Wilde;H. Van de Sompel。IETF。2022 年 7 月。建议标准。 URL: https://www.rfc-editor.org/rfc/rfc9264
[RFC9512]
YAML 媒体类型。R. Polli;E. Wilde;E. Aro。IETF。2024 年 2 月。信息性说明。URL: https://www.rfc-editor.org/rfc/rfc9512
[SNIFF]
MIME 嗅探标准。Gordon P. Hemsley。WHATWG。活动标准。URL: https://mimesniff.spec.whatwg.org/
[SPDX-Licenses]
SPDX 许可证列表。Linux Foundation。URL: https://spdx.org/licenses/
[WHATWG-URL]
URL 标准。Anne van Kesteren。WHATWG。 活动标准。URL: https://url.spec.whatwg.org/
[xml-names11]
XML 名称空间 1.1(第二版)。Tim Bray;Dave Hollander;Andrew Layman;Richard Tobin 等。W3C。2006 年 8 月 16 日。W3C 推荐。URL: https://www.w3.org/TR/xml-names11/
[YAML]
YAML 不是标记语言(YAML™)版本 1.2。Oren Ben-Kiki;Clark Evans;Ingy döt Net。2009 年 10 月 1 日。URL: http://yaml.org/spec/1.2/spec.html

H.2 说明性参考文献

[HTML]
HTML 标准。Anne van Kesteren; Domenic Denicola;Dominic Farolino;Ian Hickson;Philip Jägenstedt;Simon Pieters。WHATWG。活动 标准。URL: https://html.spec.whatwg.org/multipage/
[HTML401]
HTML 4.01 规范。Dave Raggett; Arnaud Le Hors;Ian Jacobs。W3C。2018 年 3 月 27 日。W3C 推荐。URL: https://www.w3.org/TR/html401/
[OpenAPI-Learn]
OpenAPI — 入门与规范解读。OpenAPI Initiative。URL: https://learn.openapis.org/
[RFC1738]
统一资源定位符(URL)。T. Berners-Lee;L. Masinter;M. McCahill。IETF。1994 年 12 月。建议标准。URL: https://www.rfc-editor.org/rfc/rfc1738
[RFC1866]
超文本标记语言 - 2.0。T. Berners-Lee;D. Connolly。IETF。1995 年 11 月。历史性规范。URL: https://www.rfc-editor.org/rfc/rfc1866
[RFC2396]
统一资源标识符(URI):通用语法。T. Berners-Lee;R. Fielding;L. Masinter。IETF。1998 年 8 月。草案标准。URL: https://www.rfc-editor.org/rfc/rfc2396
[RFC2557]
聚合文档的 MIME 封装(例如 HTML)(MHTML)。J. Palme;A. Hopmann;N. Shelness。IETF。1999 年 3 月。建议标准。URL: https://www.rfc-editor.org/rfc/rfc2557
[RFC6838]
媒体类型规范与注册程序。N. Freed;J. Klensin;T. Hansen。IETF。2013 年 1 月。最佳当前实践。URL: https://www.rfc-editor.org/rfc/rfc6838
[RFC7464]
JSON 文本序列。N. Williams。IETF。2015 年 2 月。建议标准。URL: https://www.rfc-editor.org/rfc/rfc7464
[RFC8091]
用于 JSON 文本序列的媒体类型结构后缀。E. Wilde。IETF。2017 年 2 月。信息性说明。URL: https://www.rfc-editor.org/rfc/rfc8091
[RFC9535]
JSONPath:用于 JSON 的查询表达式。S. Gössner,编;G. Normington,编;C. Bormann,编。IETF。2024 年 2 月。建议标准。URL: https://www.rfc-editor.org/rfc/rfc9535