OpenAPI 3.1 支持与迁移
English contract · 下载最小 JSON · 下载最小 YAML
本文描述当前 master 源码的 OpenAPI 3.1 契约。具体发布版本是否包含这些能力,请以 发布说明和 版本参考为准;本文不改变任何 starter、默认配置或发布版本。
支持范围
OpenAPI 的功能集由 major.minor 定义。3.1.x 因此使用同一套 OpenAPI 3.1 feature set,不按 patch 版本拆分能力, 离线导出也复用统一版本判断,不维护私有 patch 白名单。已有 OpenAPI 3.0.x 路径继续保留,OpenAPI 3.2.x 不在当前范围。
| 文档版本 | UI | 状态 | 说明 |
|---|---|---|---|
| Swagger / OpenAPI 2.0 | Vue 3 | 兼容维护 | 由 openapi2 starter 提供,不扩展 OAS 3.1 能力 |
| OpenAPI 3.0.x | React | 支持 | 沿用既有解析、调试、导出与变化提示路径 |
| OpenAPI 3.1.x | React | 支持 | 使用同一 feature set,并遵守下列产品边界 |
| OpenAPI 3.2.x | React | 不支持 | 不猜测或降级成 3.1 处理 |
springdoc 生成矩阵
| Spring Boot | starter / springdoc | 生成结果 | 已验证路径 | 证据 |
|---|---|---|---|---|
| Boot 2.x | openapi3 非 Jakarta / springdoc 1.8.0 | OpenAPI 3.0.x | 保持既有兼容基线 | #737 |
| Boot 3.x WebMVC | openapi3 Jakarta / springdoc 2.8.9 | 显式开启 OpenAPI 3.1 | 真实 /v3/api-docs → Java smoke → React / SchemaEngine | #737 |
| Boot 3.x WebFlux | webflux Jakarta / springdoc 2.8.9 | 显式开启 OpenAPI 3.1 | 真实 /v3/api-docs → Java smoke → React / SchemaEngine | #737 |
| Boot 4.x WebMVC | Boot4 starter / springdoc 3.0.3 | 默认或显式 OpenAPI 3.1 | 两种配置都经过端到端验证 | #737 |
Boot 3 项目显式生成 OAS 3.1 文档:
springdoc:
api-docs:
version: OPENAPI_3_1Boot 2 / springdoc 1.8.0 仍生成 OAS 3.0,不能仅修改文档中的 openapi 字符串冒充 OAS 3.1。 完整 starter 版本组合见兼容矩阵。
产品能力矩阵
除非某行另有说明,下表的“支持”指整个 OpenAPI 3.1.x feature set。
| 能力 | OAS 3.1.x 行为 | 关键边界 | 已合并证据 |
|---|---|---|---|
| 单文档与多文档加载 | 入口文档与受控跨文档资源使用同一 3.1 解析会话 | 3.2 文档拒绝进入 3.1 工作流 | #682、#689、#727 |
| 文档对象与 Webhook | 支持 paths、components、webhooks 与 3.1 Reference Object;三者至少声明一个 | Webhook 是入站契约,不等同于普通 Path 请求 | #717 |
| Schema 方言 | 使用 OAS 3.1 Base Dialect 与 JSON Schema Draft 2020-12 标准词汇 | 不把任意自定义方言解释为标准语义 | #687、#689 |
| 字段树与模型 | 支持 3.1 类型联合、布尔 Schema、const、条件与组合关键字、动态引用等 | 不执行自定义词汇;未知载荷内保留名的预扫描限制见 #740 | #692、#694 |
| 示例 | 保留作者示例并报告不一致;无作者示例时可在预算内生成确定性候选 | 不是通用 JSON Schema 求解器 | #715 |
| 参数调试 | Path、Query、Header、Cookie 按 3.1 Schema 验证,再按 style / explode 序列化 | 一个参数使用 schema 或一个 content 媒体类型;Cookie 只进入预览 / cURL,浏览器真实发送前会阻断 | #716 |
| urlencoded / multipart Body | 支持结构化字段、encoding、JSON part 与文件元数据检查 | 不读取或验证上传文件内容 | #728、#730 |
| 请求诊断 | Schema 诊断先阻止发送;同一快照可由用户显式选择“仍然发送”做负向测试 | 不绕过浏览器、安全或资源策略 | #696、#716、#728 |
| 响应诊断 | 按精确状态码、范围或 default 以及媒体类型匹配 JSON 响应 Schema | 非阻断;不验证响应 Header、Cookie、SSE 或二进制内容 | #713 |
| 单接口导出 | 完整资源图下导出可移植的单接口 OpenAPI JSON;支持 Path 与 Webhook 操作 | 不导出 YAML、ZIP、多文件包或整服务闭包 | #732、#733 |
| 接口变化提示 | 为完整资源图生成 3.1 语义指纹,与 3.0 基线隔离 | 只跟踪 paths 操作,不跟踪 Webhook 或字段级 diff | #736 |
| 离线文档 | HTML、Markdown、DOC、DOCX 使用同一不可变 3.1 快照 | 快照入口复用统一 3.1.x 版本判断;资源缺失或诊断未处理时取消,或由用户明确选择降级导出 | #734 |
真实 springdoc 到浏览器的总体验收见 #737。
JSON Schema 方言与词汇
默认方言
OAS 3.1 Schema Object 是 JSON Schema Draft 2020-12 的方言。根级 jsonSchemaDialect 未声明时, Knife4j 使用 OAS 3.1 Base Dialect:
jsonSchemaDialect: https://spec.openapis.org/oas/3.1/dialect/base当前 SchemaEngine 只执行以下两种已知方言的验证语义:
https://spec.openapis.org/oas/3.1/dialect/basehttps://json-schema.org/draft/2020-12/schema
标准与自定义词汇
JSON Schema 2020-12 的 Core、Applicator、Validation、Unevaluated、Meta-Data、Format Annotation 与 Content 标准词汇按方言处理。format 默认是注解,不因浏览器里出现一个格式字符串就自动产生网络、文件或证书能力。
未知扩展关键字和自定义词汇载荷会保留在原始文档中;SchemaEngine 会话成功时,复制与可移植导出也保留这些值, 但 Knife4j 不为它们定义验证、示例生成或字段树语义。
当前资源声明安全预扫描仍会递归检查任意对象载荷。未知关键字、example 或 extension 的普通数据里的 $id、$anchor、 $dynamicAnchor 可能被误当成 Schema 控制关键字;其中 $id 还会把该对象标成资源根并继续检查同级 $schema / $vocabulary,从而使会话失败。 这是 #740 跟踪的已知限制。真正的 Schema 资源根显式选择不受支持的 $schema 或声明自定义 $vocabulary 时,也会给出资源级不受支持方言诊断, 并阻止依赖完整 Schema 语义的动作。两种情况都不会回退到近似方言或执行自定义词汇。
外部 Schema 资源
SchemaEngine 自身不发起网络请求。外部 $ref、$dynamicRef 和相关基址先由 React UI 的受控资源图加载, 再以不可变 registry 交给解析、验证、导出和指纹流程。
授权范围
- 默认拒绝全部外部资源;只有文档实际发现并展示的精确 HTTP(S) URI可以被授权。
- 临时授权只对当前文档世代有效;刷新、切换分组或文档变化后失效。
- “记住授权”绑定到入口文档的规范化检索 URI 与内容摘要;URI 会保留已解析的 Origin、应用路径与分组查询参数,不会变成主机级通配授权。
- 持久化记录只保存资源 URI 哈希、脱敏展示值与授权时间,不保存凭据;每份文档最多记住 128 项,序列化记录最多 128 KiB。
- 设置页的“重置全部本地数据”会撤销已记住的授权;“清理请求缓存”不会撤销资源授权。
请求与凭据
资源请求使用浏览器 CORS、GET、credentials: omit、禁止重定向、无 referrer、无缓存,且不携带 Knife4j Authorize、Cookie、全局参数或业务请求 Header。HTTPS 入口不能降级加载 HTTP 资源,URI 也不能包含 userinfo。
服务端必须返回 200、UTF-8,以及 JSON 或 YAML 媒体类型。跨域服务还必须显式允许当前文档页 Origin。
固定预算
| 预算 | 上限 |
|---|---|
| 单资源解码后大小 | 4 MiB |
| 全部资源解码后大小 | 16 MiB |
| 外部文档数 | 64 |
| 引用数 | 10,000 |
| 引用深度 | 32 |
| 单文档解析节点 | 100,000 |
| 全图解析节点 | 250,000 |
| Schema 资源数 | 1,000 |
| 并发请求 | 4 |
| 单请求超时 | 10 秒 |
| 一轮加载总时长 | 30 秒 |
| 显式重试 | 每个资源 1 次 |
| YAML alias | 100 |
未授权、CORS、媒体类型、解析、重定向、超时或预算失败都会变成结构化、脱敏的资源诊断。 任何依赖完整闭包的动作都会保持不可用,不会偷偷回退到缺引用的结果;文档浏览仍可显示已加载内容和诊断。
浏览器调试边界
OpenAPI 能表达某项契约,不代表浏览器 JavaScript 能安全地发送它。
| 场景 | 文档展示 | 浏览器调试 |
|---|---|---|
TRACE | OAS 3.1 Path Item 可展示 | Fetch 禁止发送 |
CONNECT / TRACK | 仅兼容输入到达调试器时展示 | Fetch 禁止发送;它们不是 OAS 3.1 Path Item 固定字段 |
GET / HEAD request body | Schema、示例和 cURL 可展示 | Fetch 禁止带 body |
| 显式 Cookie 参数 | Schema 验证、序列化预览和 cURL 可展示 | 浏览器禁止脚本设置 Cookie Header,真实发送前阻断 |
| Webhook | 展示、字段树、离线文档和完整闭包下的单操作导出 | 仅描述入站回调,不从文档页主动发送 |
mutualTLS | 识别并展示安全方案 | UI 不存储或注入客户端证书;应在浏览器、操作系统或受信代理配置 |
| 跨域 Schema | 已授权资源可参与解析 | 仍受 CORS 和上述无凭据策略限制 |
| 负向测试 | 可显式忽略当前请求 Schema 诊断 | 只跳过 Schema 阻断,不绕过 Fetch、鉴权或资源策略 |
这些边界由 浏览器请求限制测试、 文档对象 #717、请求诊断 #696 与资源安全 #727 固化。
从 OpenAPI 3.0 迁移
迁移时应让生成器真正输出 3.1 文档,并逐项检查下列语义,不要只替换 openapi 版本号。
nullable 改为类型联合
# OpenAPI 3.0
type: string
nullable: true
# OpenAPI 3.1
type: [string, "null"]布尔 Schema
# 接受任意实例
schema: true
# 拒绝任意实例
schema: false布尔 Schema 是完整 Schema,不能当成缺失 Schema。
example、examples 与 const
# OpenAPI 3.0 Schema
type: string
enum: [stable]
example: stable
# OpenAPI 3.1 Schema
type: string
const: stable
examples: [stable]Media Type、Parameter 等 OpenAPI 对象仍可能使用自身的 example / examples 字段;不要把不同对象层级机械合并。
$ref 同级关键字
# OpenAPI 3.0 Schema 常用包装
allOf:
- $ref: "#/components/schemas/User"
maxLength: 64
# OpenAPI 3.1 Schema 可以直接组合
$ref: "#/components/schemas/User"
maxLength: 64这里说的是 Schema Object。OAS 3.1 的 Reference Object 只定义 summary 与 description 两个可用同级字段, 其他同级字段不会被当作目标对象补丁。
原始二进制与编码字符串
# OpenAPI 3.0 常见原始二进制响应
content:
application/octet-stream:
schema:
type: string
format: binary
# OpenAPI 3.1 原始二进制响应
content:
image/png:
schema:
contentMediaType: image/png
# OpenAPI 3.1:JSON 字符串里承载 base64,不是原始 body
schema:
type: string
contentEncoding: base64
contentMediaType: image/pngKnife4j 也保留对生成器仍输出 type: string + format: binary 的兼容显示;contentEncoding 表示编码后的字符串, 不能被解释成浏览器文件对象或原始上传体。
Webhook 与双向 TLS
webhooks:
paymentSettled:
post:
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/PaymentEvent"
responses:
"204":
description: Callback accepted
components:
securitySchemes:
ClientCertificate:
type: mutualTLSWebhook 描述的是 API 提供方向调用调用方的入站契约;它不是普通 paths 请求。mutualTLS 只声明安全方案, 客户端证书仍由浏览器、操作系统或受信代理持有。
最小有效夹具
仓库提供语义等价、可直接下载的两个最小文档:
它们包含 OAS 3.1 Base Dialect、const、可空类型联合和 Media Type examples,可用于验证加载、字段树、示例与响应诊断。
语言与诊断一致性
本页与 English contract 使用同一版本、能力、安全和迁移边界。React UI 的现有 OAS 3.1 诊断键在中文、英文和日文 locale 中保持同集;locale 一致性测试 会拒绝缺失键、空翻译或插值变量不一致。切换语言不会改变诊断代码或放宽策略。