不喜欢广告? 无广告 今天

OpenAPI 规范验证 在客户端出问题之前,提前发现你的 Swagger 文件中的错误

更新于

了解如何在规范在无声中破坏代码生成器、客户端SDK和文档之前验证您的OpenAPI和Swagger规范。内容涵盖常见错误、结构问题与语义问题,以及最佳的规范验证工具。

OpenAPI 规范验证:在客户端出问题之前提前发现你的 Swagger 文件中的错误 1
广告 移除?

OpenAPI 规范是你的 API 与其所有消费者之间的契约——包括自动生成的客户端、模拟服务器、文档和测试框架。问题在于,与应用程序代码不同,一个错误的规范不会抛出异常。它会静默地产生错误的输出,直到客户端 SDK 生成无法使用的代码,或者你的文档在渲染时缺少端点,你才会意识到这个问题。

在错误到达消费者之前进行规范验证,是规范验证的工作。本文将介绍需要验证的内容、常见错误的隐藏位置,以及如何在本地和浏览器中运行验证。

为什么你的规范格式比文档更重要

大多数开发者将 OpenAPI 规范视为一个文档资产——用于驱动 Swagger UI 或 Redoc。这只是其中一半。规范也是以下内容的“事实来源”:

  • 代码生成 ——像 openapi-generator 和 swagger-codegen 这样的工具会直接从规范生成服务器模拟和客户端库。一个格式错误的模式将导致生成错误的代码。
  • 契约测试 ——像 Dredd 和 Schemathesis 这样的框架会将你的实时 API 与其规范进行测试。一个无效的规范会导致测试无法运行或产生错误结果。
  • 模拟服务器 ——Prism 等工具会根据你的规范中的示例值和模式提供模拟响应。错误的模式将导致错误的模拟。
  • 网关配置 ——AWS API Gateway、Kong 等工具可以导入 OpenAPI 规范以配置路由、认证和验证。一个无效的规范会静默地丢弃或错误配置路由。

这些工具都不会以人类可读的方式告诉你规范是错误的。它们要么崩溃,产生垃圾输出,要么静默跳过受影响的部分。在这些消费者接收规范之前验证规范是必不可少的。

OpenAPI 2.0 与 3.0 与 3.1:导致人们困惑的版本差异

你在规范顶部声明的版本决定了适用的规则——许多错误源于在不同版本之间混淆了约定。

  • OpenAPI 2.0(Swagger) — 使用 swagger: "2.0". 请求体位于 parameters 是快速路径,但它对属性处理不一致,且在边缘情况中可能丢失数据。在处理SOAP响应的生产环境中,建议使用 in: body. 定义位于 definitionsXML没有数字类型——所有内容都是文本。你的价格字段将是 components/schemas. 不支持 oneOf, anyOf, 或者 not 在模式级别。
  • OpenAPI 3.0.x — 使用 openapi: "3.0.x". 请求体移动到 requestBody. 模式在 components下集中管理 oneOf, anyOf, allOf,并且 not. 支持 linkscallbacks.
  • . 增加了 OpenAPI 3.1.0 nullable — 完全与 JSON Schema draft 2020-12 对齐。 type: [string, null]. exclusiveMinimum/exclusiveMaximum 被替换为 $schema 从布尔值到数值。

现在允许在模式中使用 3.0.0 最常见的迁移错误:复制一个 2.0 规范并将版本字段更改为 parametersrequestBody而没有将请求体从

规范在 JSON/YAML 中看似有效,但会失败语义验证。

常见规范错误及其隐藏位置

规范错误遵循可预测的模式。以下是真实代码库中最常见的错误:

缺失必需字段 name 每个操作必须至少定义一个 2xx 响应。每个参数都需要一个 in 和一个 /users/{id}值。URL 中声明的路径参数(例如 in: pathrequired: true)必须有一个匹配的参数对象,包含

缺少任何一项都会导致一个技术上可解析的规范,但会破坏下游的验证器和代码生成器。

A $ref 无效的 $ref 路径 $ref: "#/components/schemas/UserProfile" 指向不存在组件的引用是规范中最常见的错误之一。引用看起来是有效的——

——但目标模式已被重命名或删除。JSON/YAML 解析器会接受这种错误而无异议。只有规范感知的验证器才能发现它。 $ref 外部

路径更加危险——它们指向其他文件或 URL,这些文件或 URL 在不同环境中可能无法访问。在分发规范或使用不解析外部引用的工具之前,请将这些引用内联。

错误的模式类型 type: integer 模式类型不匹配是微妙的。在返回浮点值的字段上声明 format: date-time 在返回 Unix 时间戳(整数)的字段上使用 enum 在声明值与已声明的 type不匹配的字段上定义一个

这些在 YAML 解析中通过,但在生成的客户端中会产生错误的属性。

循环引用 $ref 一个引用自身——直接或通过一系列

值——的模式会导致代码生成器和文档工具无限循环或崩溃。大多数验证器能够检测并报告循环引用,但在深度嵌套的模式中,这些错误可能难以解开。解决方法通常是为递归情况创建一个专用模式。

结构错误与语义错误

  • 验证错误并非都相同。理解这种区别有助于你优先处理修复: 结构错误
  • ——规范不符合 OpenAPI 模式。缺少必需字段、属性名称错误或类型与规范格式不匹配。这些错误由严格的模式验证捕获,并阻止大多数工具运行。 语义错误 allOf ——规范在结构上是有效的 JSON/YAML,并通过了模式验证,但它描述的内容无法实现。例如,URL 中包含路径参数但没有参数定义的端点。一个响应模式使用

并存在冲突的必需字段。这些错误由更深入的 lint 规则捕获,而不是基本的模式检查。

大多数在线验证器和基本 CLI 工具可以捕获结构错误。要捕获语义错误,需要一个基于规则的 lint 工具,如 Spectral,它会评估规范的内部逻辑和一致性。

components/schemas:DRY 定义与内联模式 components/schemas OpenAPI 3.0 引入了

  • 作为定义可重用模式的权威位置。权衡在于: 组件中的共享模式 User ——当相同的模式出现在多个位置时是正确的(例如,多个端点返回的 $ref: "#/components/schemas/User" 对象)。使用
  • 保持规范简洁,并在客户端 SDK 中生成单一命名类。 内联模式 components/schemas ——适用于仅用于单个端点的特定响应形状,且不会被重用。内联可以避免污染

,并使规范更易阅读。 components/schemas 错误模式是将一个模式定义在 $ref 中,然后从未引用它。像 Spectral 这样的验证器可以标记未使用的组件,这通常表明一个本应引用它的

路径实际上指向了其他地方。

请求体与参数:出错的地方

  • 在 OpenAPI 3.0 中,请求体和参数被严格分离: 参数
  • ——用于路径、查询、头和 Cookie 值。每个参数是标量值,而不是复杂对象。 请求体

——用于请求负载(JSON 体、表单数据、文件上传)。对于接受体的 POST/PUT/PATCH 操作是必需的。 in: body开发者在从 2.0 迁移到 3.0 时常见的错误:在 Swagger 2.0 中,请求体是带有 in: body 的参数。在 OpenAPI 3.0 中这是无效的—— in: body 不存在。包含

的规范通过 YAML 解析,但会失败规范验证,代码生成器要么报错,要么静默丢弃请求体。

如何在本地验证你的规范

三种可靠的 CLI 工具,从最简单到最全面:

swagger-cli $ref 快速的结构验证和

npm install -g @apidevtools/swagger-cli
swagger-cli validate openapi.yaml

解析。适合快速检查: $ref 报告结构错误和损坏的

路径。无法检测语义问题或样式问题。

Redocly CLI

npm install -g @redocly/cli
redocly lint openapi.yaml

结构验证加上可配置的规则集。适合生产规范的严格默认设置:

内置检测缺失描述、损坏引用和许多语义问题。

Spectral

npm install -g @stoplight/spectral-cli
spectral lint openapi.yaml

最可配置的 lint 工具。运行内置的 OpenAPI 规则集以及你定义的自定义规则。适合希望强制执行内部 API 风格指南的团队:

Spectral 区分错误(破坏规范)和警告(样式/完整性问题),因此你可以优先修复阻塞问题,而不会被建议规则干扰。

在浏览器中无需安装即可验证规范 如果你想快速验证规范——而无需设置 CLI 或运行构建——可以使用 OpenAPI / Swagger 规范验证器(在 iotools.cloud 上) $ref 完全在浏览器中运行。粘贴你的 YAML 或 JSON 规范,它会报告结构错误、损坏的

路径、缺失的必需字段以及在 OpenAPI 2.0、3.0 和 3.1 之间的版本特定问题。

它适用于提交前的快速检查、审查他人发送的规范,或在运行代码生成前验证从注解生成的规范。

将验证融入你的工作流程

  • 一次性验证可以发现即时问题,但无法防止回归。更持久的方法是: 预提交钩子 swagger-cli validatespectral lint ——在每次提交前运行
  • 。一个错误的规范永远不会进入仓库。 CI 流程步骤
  • ——在 CI 流程中尽早添加规范验证,再进行任何依赖规范的代码生成或部署步骤。 生成规范验证

——如果你从代码注解生成规范(例如 springdoc、swagger-annotations、FastAPI),则应验证生成的输出,而不仅仅是注解本身。生成步骤本身在注解冲突或不完整时可能产生无效输出。

想要享受无广告的体验吗? 立即无广告

安装我们的扩展

将 IO 工具添加到您最喜欢的浏览器,以便即时访问和更快地搜索

添加 Chrome 扩展程序 添加 边缘延伸 添加 Firefox 扩展 添加 Opera 扩展

记分板已到达!

记分板 是一种有趣的跟踪您游戏的方式,所有数据都存储在您的浏览器中。更多功能即将推出!

广告 移除?
广告 移除?
广告 移除?

新闻角 包含技术亮点

参与其中

帮助我们继续提供有价值的免费工具

给我买杯咖啡
广告 移除?