跳至主要内容

从 OpenAPI 3.0 迁移到 3.1.0

作者: 2021 年 2 月 16 日博客

这篇文章的作者是 Phil Sturgeon,Stoplight 的产品经理,以及 Protect Earth 的主席。如果您想捐赠给 Phil 选择的慈善机构,请查看 Protect Earth,该机构正在逐步重新造林英国。

OpenAPI v3.1 带来了许多 很棒的新功能和改进,在不久的将来,您可能会发现自己想要升级。如果您准备尝试一下,让我们看看为了升级到 OpenAPI v3.1,您可能需要或不需要进行哪些更改。

首先,让我们更改版本号!打开您的 OpenAPI JSON 或 YAML 文件,并查找以下行

openapi: 3.0.3

将其更改为。

openapi: 3.1.0

如果看到的是 `swagger: 2.0` 而不是 `openapi: 3.0.3`,请查看 swagger2openapi 是否可以帮助您升级到 v3.0,然后再继续。

在一个理想的世界中,这将是您需要做的全部工作,但尽管版本号较小,v3.1 确实有一些小的重大更改。做出这个决定并非易事。值得庆幸的是,重大更改的范围非常小,仅限于 Schema 对象,并实现了更大的目标:与现代 JSON Schema 完全兼容。

OpenAPI Schema 现在是有效的 JSON Schema

OpenAPI 中 `schema` 关键字内的所有内容都由 Schema 对象 定义。它一直都松散地基于 JSON Schema,并被称为“子集超集”,因为它在 JSON Schema 的基础上添加了一些内容,并删除了一些其他内容。这给 OpenAPI 社区中的一些人带来了困惑。为了解决子集超集问题,来自这两个社区的贡献者走到一起,使这两个规范保持一致。

OpenAPI v3.0 基于 JSON Schema Draft 05,而 JSON Schema 从那时起经历了一些版本:Draft 06、Draft 07 和 Draft 2019-09。现在,由于在 v3.1.0 发布候选版本期间从用户和工具维护人员那里收集到的反馈,发布了一个更小的版本:Draft 2020-12。这应该是一段时间内的最后一个版本,JSON Schema 团队没有计划进行重大更改,因此,如果一切顺利,最终版本即将发布,以避免任何进一步的差异。

支持现代 JSON Schema 带来了许多方便的新功能,包括能够使用 元组的 items 数组,或使用 if/then/else 关键字作为笨拙的嵌套 allOf > oneOf 链的替代方案,有些人使用这些链来处理更动态的有效负载。我们现在不需要学习 JSON Schema 的所有新功能,但如果要升级,我们需要知道在 OpenAPI 文档中需要更改什么。

Schema 对象更改

将 nullable 替换为 type 数组

与 JSON Schema 一致,`type` 关键字现在可以使用数组为架构定义多种类型。这是一个有用的新功能,但也使得 nullable 变得多余。为了实现让 JSON Schema 工具理解 OpenAPI 的目标,决定完全删除 nullable 而不是弃用它。

# OpenAPI v3.0
type: string
nullable: true

# OpenAPI v3.1
type:
- "string"
- "null" 

这遵循关键字独立性概念,即关键字应该只添加约束,但添加一个额外的关键字不应该删除约束。查找和替换应该可以快速解决此问题。

调整 exclusiveMinimum 和 exclusiveMaximum

这两个关键字以前采用布尔值,该值会修改 `minimum` 和 `maximum` 属性的含义。在 OpenAPI v3.1 中,它们是不同的值。

# OpenAPI v3.0
minimum: 7
exclusiveMinimum: true
# OpenAPI v3.1
exclusiveMinimum: 7

同样,这可以通过一些查找和替换来解决,而且我敢打赌,你们中的许多人甚至都没有将此关键字用于任何用途。

使用 examples 而不是 example

OpenAPI 有很多地方可以有一个示例或多个示例。OpenAPI v3.0 可以在媒体类型级别(请求、响应、回调和 Webhook)使用 `example` 或 `examples`,但它也可以在 Schema 对象内部使用非常不同的 `example` 类型。此架构对象单一示例是一个 OpenAPI 特定的关键字,现在不再需要,因为 JSON Schema 具有 `examples`。

这可能需要可视化,我将推迟到 Lorna Mitchell,因为她在 APIDays Paris 的演讲中制作了一些优秀的幻灯片。

# OpenAPI v3.0
type: string
example: fedora
# OpenAPI v3.1
type: string
examples: 
 - fedora

基本上将 `schema` 内部的任何 `example` 切换到 `examples`,并在开头添加一个连字符(这是一个 YAML 数组)。

如果您完全手动编写 YAML 而不是使用可视化编辑器,这需要更多输入,但它也是一项功能:现在添加多个示例变得容易得多。过去,要为属性或架构获取多个示例,您必须切换正在使用的示例类型,从属性示例切换到媒体类型示例,这感觉有点过头了。现在您可以这样做

type: string
examples: 
 - fedora
 - ubuntu

描述文件上传有效负载

在 OpenAPI v3.0 中,描述文件上传是通过类型:字符串和格式设置为字节、二进制或 base64 来指示的。JSON Schema 通过其 contentEncoding 和 contentMediaType 关键字使这一点更加清晰,这些关键字专为这种用途而设计。

在 POST 请求中上传二进制文件?现在甚至不需要使用架构。

# OpenAPI v3.0
requestBody:
  content:
    application/octet-stream:
      schema:
        type: string
        format: binary

# OpenAPI v3.1

# OpenAPI v3.1
requestBody:
  content:
    application/octet-stream: {}

使用 base64 编码上传图像?

# OpenAPI v3.0
requestBody:
  content:
    image/png:
      schema:
        type: string
        format: base64
# OpenAPI v3.1
requestBody:
  content:
    image/png:
      schema:
        type: string
        contentEncoding: base64

包含二进制文件的 Multipart 文件上传?

# OpenAPI v3.0
requestBody:
  content:
    multipart/form-data:
  	schema:
       type: object
       properties:
        orderId:
          type: integer
        fileName:
          type: string
          format: binary
# OpenAPI v3.1
requestBody:
  content:
    multipart/form-data:
  	schema:
       type: object
       properties:
        orderId:
          type: integer
        fileName:
          type: string
          contentMediaType: application/octet-stream

此关键字支持 RFC4648 中定义的所有编码,包括“base64”和“base64url”,以及 RFC2045 中的“quoted-printable”。

声明 $schema 方言以防止更改

这就是您需要更改的内容,我还可以讨论其他许多功能,但有一件事可以帮助避免将来发生更改,那就是能够在架构中定义 $schema。

$schema 现在允许

$schema 关键字是可选的,但它是一种有用的方法,可以准确定义模型使用的是哪种 JSON Schema 方言,这可能是不同的版本,甚至自定义方言。支持多种方言的工具可以以略微不同的方式处理文件,这意味着将来升级 OpenAPI 版本时,您并不总是需要对所有模型进行更改。

OpenAPI 与 JSON Schema 完全兼容,因为它现在是 JSON Schema 的一种方言,因此默认情况下,任何架构都使用 `$schema. “https://spec.openapis.org.cn/oas/3.1/dialect/base”` 方言。如果您将架构拆分为其他 JSON/YAML 文件并使用 $ref 指向它们,则它们可能包含不同的 $schema 并覆盖此默认值。

{
   $schema: "http://json-schema.org/draft-07/schema#",
}

这使工具维护人员的工作变得容易得多,因为他们不再需要尝试通过查看架构引用的位置来猜测架构是什么版本。过去,这会产生不可能的情况,即单个架构同时被 OAS2 和 OAS3 引用,并且可能工作了一段时间,直到添加了 OAS3 特定的关键字,现在 OAS2 的所有用法都已损坏。

现在,所有模型都可以声明自己的方言,如果 OpenAPI 文档引用了工具无法理解如何解析的方言,则会立即清楚,而不是在使用几个月后出现故障并让每个人都感到困惑。