Skip to content

Swagger / OpenAPI · 高频面试题(30+)

涵盖前端、后端、测试 / QA 三类岗位真题。难度从 ⭐ 入门到 ⭐⭐⭐⭐⭐ 专家。每题都给"简短答案 + 展开"两种深度,按场合(电话面 / 现场白板)选用。


🌱 入门题(⭐ — ⭐⭐)

1. Swagger 和 OpenAPI 是同一个东西吗?

简短答:不是。OpenAPI 是规范Swagger 是工具

展开

  • 2010 年:Tony Tam 在 Wordnik 公司开发 Swagger(包含规范 + UI + Codegen 一整套)
  • 2015 年:SmartBear 收购 Swagger,把"规范"捐给 Linux 基金会,更名为 OpenAPI Specification (OAS)
  • 从此:OpenAPI = 规范(YAML/JSON 怎么写);Swagger = 工具家族(Swagger UI / Editor / Codegen)
  • 日常口语两者经常混用,但面试时讲清这层关系会加分

2. 为什么要用 Swagger,不用 Word 文档 / 语雀?

简短答:Word 文档 = "手写菜单",会过期;Swagger = "机器可读的菜单",能自动生成 SDK / Mock / 测试集合,且永远跟代码同步。

展开

  • 准确性:Word 容易过期;OpenAPI 是 code-first 自动导出的,不会撒谎
  • 可运行:Swagger UI 自带 Try it out,所见即所得
  • 自动化:一份 yaml → 50+ 语言 SDK + 后端骨架 + Mock + Postman 集合
  • 跨语言协作:所有人看同一份"事实源",不用群里追后端问字段

3. OpenAPI 的根字段必填的有哪几个?

简短答:3 个 — openapiinfo(含 title + version)、paths

展开

yaml
openapi: 3.0.3        # 必填
info:                 # 必填,里面 title 和 version 必填
  title: My API
  version: 1.0.0
paths: {}             # 必填,可以是空对象

servers / components / tags / security / externalDocs 都是可选。


4. openapi.yamlopenapi.json 区别?

简短答:等价。两种格式工具都支持,人手写选 yaml,机器输出多是 json

展开

  • yaml 更紧凑(小 30%)、支持注释、缩进易读但易出错
  • json 工具兼容性最好,但啰嗦、不能写注释
  • 后端框架(Spring / FastAPI)自动暴露的多是 json
  • 可以用 yqjs-yaml 互转

5. Swagger UI 和 Swagger Editor 区别?

简短答:UI 是"展示器"(只读),Editor 是"编辑器"(可改可预览)。

展开

  • Swagger UI:渲染一份现成的 yaml 成漂亮的交互式文档(带 Try it out)
  • Swagger Editor:左边写 yaml,右边实时渲染(适合学习 / 手写)
  • 都能 Docker 一句话起;Editor 多用于本地开发,UI 多用于团队 / 客户

6. Swagger UI 和 Redoc 怎么选?

简短答:内部团队 / 调试用 Swagger UI(带 Try it out);外部展示 / 文档站用 Redoc(更漂亮、长文档体验更好)。

展开

维度Swagger UIRedoc
Try it out✅ 支持❌ 默认不支持
美观度⭐⭐⭐⭐⭐⭐⭐⭐
长文档一般(左侧导航 + 三栏)
自定义较弱

7. OpenAPI 2.0 和 3.0 有啥区别?

简短答3.0 重构了结构——servers 替代 host/basePathrequestBody 独立、components 集中复用、对 OAuth2 / JSON Schema 友好。

展开

维度OpenAPI 2.0 (Swagger 2)OpenAPI 3.0 / 3.1
顶层字段swagger: "2.0"openapi: 3.0.3
服务器地址host + basePath + schemesservers 数组
请求体混在 parameters 里独立 requestBody
复用区definitions 等平铺统一进 components
多 MIMEconsumes / produces每个 contentType 独立
OAuth2不直观重写、字段清晰
JSON Schema部分兼容3.1 完全兼容 (2020-12)

8. yaml 里 200 状态码为啥要加引号?

简短答:yaml 把裸的 200 解析成数字;OpenAPI 规定状态码必须是字符串

展开

yaml
# ✗ 错(200 被当数字)
responses:
  200:
    description: OK

# ✓ 对
responses:
  '200':
    description: OK

类似的:'true' / 'false' / 'on' / 'off' 在 yaml 里别裸写,否则被当 boolean。


🌿 进阶题(⭐⭐⭐)

9. $ref 是什么?常见错误?

简短答$ref 是 OpenAPI 的引用机制,让你复用 schema / parameters / responses / examples。语法是 JSON Pointer。

展开

yaml
# 当前文件内(最常见)
$ref: '#/components/schemas/User'

# 其他文件
$ref: './schemas/user.yaml#/User'

常见坑

yaml
# ✗ 漏 #
$ref: 'components/schemas/User'

# ✗ 拼写
$ref: '#/components/schema/User'   # schemas 漏 s

# ✗ $ref 不能跟其他字段并列
schema:
  $ref: '#/components/schemas/User'
  description: '用户'              # 会被忽略

10. allOf / oneOf / anyOf 的区别?

简短答

  • allOf = 全部都满足(合并 / 继承)
  • oneOf = 恰好满足其中一个(多态)
  • anyOf = 至少满足一个(可同时满足多个)

展开

yaml
# allOf:Dog = Pet + 额外字段
Dog:
  allOf:
    - $ref: '#/components/schemas/Pet'
    - type: object
      properties: { breed: { type: string } }

# oneOf:付款方式只能选一种
PaymentMethod:
  oneOf:
    - $ref: '#/components/schemas/CreditCard'
    - $ref: '#/components/schemas/Alipay'
  discriminator:
    propertyName: type

# anyOf:支持多种但能复合
Search:
  anyOf:
    - type: object
      properties: { keyword: { type: string } }
    - type: object
      properties: { author: { type: string } }

工程里 90% 用 allOf(继承 + 扩展),oneOf 多用于多态请求体。


11. PUT 和 PATCH 的区别?

简短答

  • PUT = 完整替换:传整个对象,没传的字段会被清空
  • PATCH = 部分更新:只改你传的字段,其他保留

展开

http
PUT /users/1                       PATCH /users/1
{ "name": "Alice", "email": "" }   { "name": "Alice" }

→ email 被清空                     → email 保持原样

幂等性:PUT 永远幂等;PATCH 看实现({op: "+", balance: 100} 不幂等)。


12. POST 和 PUT 都能创建资源,怎么选?

简短答:URL 里不知道 ID 时用 POST(服务端生成 ID);知道 ID 时用 PUT(客户端指定 ID)。

展开

POST /users         → 服务端返回 201 + Location: /users/999(ID=999 是服务端生成)
PUT  /users/u-abc   → 客户端指定 ID 创建(如导入已有数据)

PUT 还要求幂等:连续调 N 次效果跟 1 次一样。POST 不要求幂等。


13. operationId 写不写有差别吗?

简短答强烈推荐写。codegen 用它当生成的方法名,写了名字漂亮(createUser()),不写就是丑的(usersPost())。

展开

yaml
post:
  operationId: createUser           # ← 推荐

→ 生成的 SDK:api.createUser({...}) → 不写则可能:api.usersPost({...})api.users_create({...})

约定:驼峰 + 动词在前。在整份 yaml 里 operationId 必须唯一


14. path 参数为什么必须 required: true

简短答:URL 里的 {} 没法"省略",所以一定要传。OpenAPI 规范强制要求。

展开

yaml
- name: id
  in: path
  required: true     # ← path 永远 true
  schema: { type: integer }

false 工具会报错。其他位置(query / header / cookie)默认 false


15. query 数组在 URL 里怎么表示?

简短答:通过 style + explode 控制:

styleexplodeURL
formtrue?tags=a&tags=b默认
formfalse?tags=a,b
spaceDelimitedfalse?tags=a%20b
pipeDelimitedfalse?tags=a|b

展开:实际工程保持默认就好(form + explode=true),最兼容。


16. 文件上传怎么写?

简短答:用 multipart/form-data + format: binary

展开

yaml
requestBody:
  content:
    multipart/form-data:
      schema:
        type: object
        properties:
          file:
            type: string
            format: binary       # ← 关键
          description:
            type: string
        required: [file]

多文件:file: { type: array, items: { type: string, format: binary } }


17. readOnly / writeOnly 啥用?

简短答readOnly 字段只在响应里出现,请求体不传(如 id / createdAt);writeOnly 反过来(如 password)。

展开

yaml
User:
  type: object
  properties:
    id: { type: integer, readOnly: true }
    password: { type: string, writeOnly: true }
    email: { type: string }

代码生成时:

  • 创建 / 更新的 DTO 类型自动剔除 readOnly 字段
  • 响应类型自动剔除 writeOnly 字段
  • 类型更安全,前端不会误传 id

18. Authorization 头要写在 parameters 还是 securitySchemes?

简短答securitySchemes!parameters 不允许描述安全相关的头。

展开

yaml
# ✗ 错
parameters:
  - name: Authorization
    in: header
    schema: { type: string }

# ✓ 对
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
security:
  - bearerAuth: []

写到 parameters 不会报错,但 Swagger UI 不会出现 🔒 Authorize 按钮,不规范。


19. 前端 Try it out 跨域怎么办?

简短答:让后端开 CORS(Access-Control-Allow-Origin);或前面挂 Nginx 反向代理同源。

展开

Swagger UI 的 Try it out 是浏览器从你电脑发的真实请求,跨域时浏览器会拒绝。

# 后端临时方案:Spring Boot
@CrossOrigin(origins = "*")
@RestController public class XxxController { ... }

# Nginx 反向代理把 /api 代理到后端,从而同源

🌳 高级题(⭐⭐⭐⭐)

20. JWT 的 payload 是加密的吗?

简短答不是!只是 base64 编码,谁拿到 token 都能解出来。

展开

header.payload.signature
  ↑       ↑       ↑
  |       |       └─ 服务端用密钥签名,防篡改
  |       └────────── base64({"sub": "123", "exp": ..., "role": "admin"})
  └────────────────── base64({"alg": "HS256"})

把整段 token 贴到 https://jwt.io 立刻能看 payload 全部内容。所以

  • ❌ 别在 payload 里塞密码、隐私信息
  • ✅ 只放 user_id、role、过期时间这种"非敏感的元信息"
  • 安全靠的是 signature:篡改 payload 后服务端算签名对不上,就拒绝

21. OAuth2 的 4 种 flow 选哪个?

简短答

Flow用谁现状
authorizationCodeWeb 应用 + 后端✅ 推荐
authorizationCode + PKCESPA / 移动端✅ SPA 首选
clientCredentialsM2M (服务到服务)✅ 后端通信
password第一方应用⚠️ 不推荐
implicit老 SPA❌ 已废弃

展开implicit 因为 token 走 URL fragment 易泄漏(浏览器历史 / 日志)已经被 OAuth2.1 废弃,新 SPA 用 authorizationCode + PKCE


22. swagger-codegen 和 openapi-generator 选哪个?

简短答openapi-generator

展开

  • swagger-codegen:Swagger 官方早期工具,更新慢
  • openapi-generator:2018 年从 swagger-codegen v2 fork,社区维护、活跃度高、模板多
  • 新项目无脑选 openapi-generator

23. springfox 和 springdoc-openapi 选哪个?

简短答springdoc-openapi。springfox 已停止维护,且只支持 OpenAPI 2.0。

展开

  • springfox:老项目用得多,最后版本 3.0 仍然只是 OpenAPI 2.0
  • springdoc-openapi:原生支持 OpenAPI 3,活跃维护,跟 Spring Boot 3 兼容好
  • 迁移命令大概率把 @Api@Tag@ApiModelProperty@Schema

24. @nestjs/swagger 的 CLI 插件是干啥的?

简短答自动从 TS 类型推断 schema,让你不用写 @ApiProperty

展开

nest-cli.json

json
{
  "compilerOptions": {
    "plugins": [
      { "name": "@nestjs/swagger", "options": { "introspectComments": true } }
    ]
  }
}

效果:

ts
// 不写 @ApiProperty 也能从类型自动生成 schema
export class CreateUserDto {
  /** 邮箱 */
  email: string;
  /** 年龄 */
  age?: number;
}

注释 → description,类型 → schema 类型,? → optional。少写一半注解


25. design-first vs code-first 怎么选?

简短答

  • 大型团队 / 多语言后端:design-first(先评审 yaml,再各自实现)
  • 个人 / 小项目:code-first(边写代码边出文档)

展开

维度design-firstcode-first
团队规模大(5+ 人)
启动速度慢(要先讨论 yaml)
yaml 质量高(评审过)一般(容易"脏")
同步成本容易代码 / 文档不同步

很多大团队用 hybrid:先 design 锁定 + code-first 实现 + CI 校验两者一致。


26. 接口变更怎么及时通知前端?

简短答:CI 里跑 openapi-diff 检测 breaking change,自动评论 PR;CI 自动重新生成 SDK 并发布 npm。

展开

yaml
# GitHub Action
- name: Diff
  run: |
    git fetch origin main
    npx -y openapi-diff origin/main:openapi.yaml openapi.yaml \
      --fail-on-incompatible

- name: Generate SDK
  run: npx @openapitools/openapi-generator-cli generate \
       -i openapi.yaml -g typescript-axios -o sdk

- name: Publish npm
  run: cd sdk && npm publish --access public

前端 npm update @company/api-sdk,TypeScript 编译就告诉你哪行用了已删字段。


27. 怎么给一个老项目从 0 加 Swagger?

简短答

  1. 梳理现有接口:列 URL + 参数 + 响应到表格
  2. 写 yaml(design-first)或后端框架挂注解(code-first)
  3. 挂 Swagger UI 让大家看
  4. CI 跑 spectral lint
  5. 跑 schemathesis 模糊测试:把 yaml 跟实际服务对比,找出不一致
  6. 逐步生成 SDK 替换前端手写的 axios 调用

展开:通常痛点是接口定义不规范(命名乱 / 无版本 / 错码不统一),加 Swagger 是重新审视 API 设计的契机。


28. Mock 服务(Prism)有什么用?

简短答前端不用等后端——一份 yaml 直接起 Mock,返回符合 schema 的假数据。

展开

bash
docker run -p 4010:4010 -v $PWD:/spec stoplight/prism:4 mock /spec/openapi.yaml

特点:

  • 自动按 schema 生成响应(或用你写的 example
  • 自动按 schema 验证请求体(前端传错字段直接拒绝)
  • 配合 --dynamic 能生成更随机的数据
  • 配合 --errors 能模拟错误响应(给前端测错误处理用)

29. spectral 是干啥的?

简短答:OpenAPI 的 lint 工具,给文档质量打分。

展开

bash
npx -y @stoplight/spectral-cli lint openapi.yaml

默认规则集(spectral:oas)会检查:

  • 每个 operation 是否有 summary / description
  • 每个 schema 是否有 example
  • path 和 method 命名是否规范
  • 是否有未使用的 components

可以自定义规则,强制团队约定(如"所有 operationId 必须驼峰")。CI 里强烈推荐挂上。


30. 什么是 schemathesis?

简短答:基于 OpenAPI yaml 自动生成模糊测试——按 schema 生成各种边界值发请求,找后端 bug。

展开

bash
pip install schemathesis
schemathesis run http://localhost:8000/openapi.json

它会:

  • 随机组合参数(边界值、空值、超长字符串、负数、特殊字符)
  • 检查响应是否符合 yaml 里定义的 schema
  • 自动发现 5xx 错误和 schema 不一致

业内最强 API 测试武器之一,CI 里跑一遍能炸出 80% 后端隐藏 bug。


🌲 专家题(⭐⭐⭐⭐⭐)

31. 如何处理"接口废弃"的 lifecycle?

简短答

  1. 先标 deprecated: true(UI 画删除线 + 警告)
  2. description 写明"请改用 X 接口,将于 YYYY-MM 删除"
  3. 监控访问日志,等使用率降到 0 再真删
  4. 用 openapi-diff 提示"删除接口"为 breaking change

展开

yaml
/v1/users:
  get:
    deprecated: true
    summary: '[废弃] 请改用 /v2/users'
    description: |
      ⚠️ 本接口将于 **2026-01-01** 删除。
      请改用 [/v2/users](#operations-tag-user-listUsersV2)。

32. 如何在文档里维护多版本(v1 / v2)?

简短答:两种主流:

  • 路径前缀/v1/users/v2/users单文档
  • 多文档v1/openapi.yamlv2/openapi.yaml,UI 顶部下拉切换

展开

yaml
# 单文档 + 路径前缀(推荐)
paths:
  /v1/users:
    get: { deprecated: true, ... }
  /v2/users:
    get: { ... }

servers.url不要/v1/v2,让路径里自己带版本,扩展性更好。


33. 接口字段变更怎么不破坏老客户端(向后兼容)?

简短答只加不改——加新字段可,改字段名 / 删字段是 breaking。

展开

操作是否 breaking
加可选 query / 字段❌ 安全
加必填字段✅ breaking
改字段类型(int → string)✅ breaking
删字段✅ breaking
改响应字段名✅ breaking
加新 enum 值⚠️ 可能 break(严格模式下客户端会拒绝未知值)
改 endpoint 路径✅ breaking
加新 endpoint❌ 安全

CI 里挂 openapi-diff --fail-on-incompatible,PR 自动拦截。


34. OpenAPI 3.1 比 3.0 强在哪?

简短答完全兼容 JSON Schema 2020-12 + 新增 webhooks + nullable 改写法。

展开

功能OpenAPI 3.0OpenAPI 3.1
nullablenullable: truetype: [string, "null"]
JSON Schema子集完全兼容 2020-12
webhooks没有顶层 webhooks 字段
examples单数 example 字符串任意 JSON
required 校验

工具生态正在追赶;新项目 3.0 / 3.1 都行,老项目维持 3.0 即可。


35. 为什么 ChatGPT Plugins / Function Calling 用 OpenAPI?

简短答:OpenAPI 是 LLM 跟 API 对话的"翻译官"——LLM 看 yaml 就知道"我能调啥、参数咋传"。

展开

LLM ─读─► openapi.yaml  ←─导─ 你的 API

  "用户问'订一杯咖啡',我要调 POST /orders,body 是..."

  LLM 自动生成符合 schema 的请求 → 调用 API → 把响应说人话给用户

新协议如 MCP (Model Context Protocol) 也借鉴了 OpenAPI 思想——OpenAPI 已经从"接口文档"进化成了"AI 时代的接口协议"


🌳 场景题(综合考察)

36. 假设你接手一个老项目,没文档,怎么 1 周内出一份 Swagger?

思路

  1. 挑工具:后端是什么栈,挂对应的 codegen(Spring → springdoc、FastAPI → 内置...)
  2. 打开 UI 看自动暴露的 yaml——80% 接口能马上有
  3. 梳理 / 补全注解@Schema@Operation),让生成的 yaml 漂亮
  4. 跑 spectral lint,按规则修
  5. 挂 Mock + 给前端发 SDK 试用,反向找 bug
  6. 接入 CI:lint + diff,防止后续退化

37. 前端发现某接口的响应字段跟文档不一致,怎么办?

思路

  1. 用 schemathesis 跑一遍,自动证明哪边对哪边错
  2. 如果代码对:让后端补 / 改注解,重新导出 yaml
  3. 如果文档对:是后端代码 bug,提 issue
  4. 长期:CI 里加 schemathesis 防止再发生

38. 团队里 3 个后端同时改 yaml,冲突频繁,怎么破?

思路

  1. 拆文件:每模块一个 paths/xxx.yamlschemas/xxx.yaml
  2. 主文件 openapi.yaml 只放顶层 + $ref
  3. redocly bundle 在 CI 里合并
  4. PR 评审锁文件 owner(git CODEOWNERS)

39. 文档需要给"外部客户"看,怎么加 access control?

思路

  1. 用 Redoc 部署成静态站,前面挂 Nginx Basic Auth
  2. 或部署到 GitHub / GitLab Pages 私有仓库
  3. 商业方案:Stoplight Hub、Redocly Workflows、Apifox 团队版

40. 接口文档要支持"按客户端权限显示不同内容",怎么办?

思路

  1. OpenAPI 本身不支持按客户端隐藏接口
  2. 实战做法:
    • 公开版(脱敏):删掉 /admin/* 后导出
    • 内部版(完整):原文件
  3. 或用 OpenAPI 扩展字段(x-internal: true)+ 自定义脚本过滤后再发布

终极总结:面试时的 3 句"必杀技"

当面试官问 "你怎么用 Swagger?",你这样答能拿满分:

  1. OpenAPI 是规范、Swagger 是工具家族;现在新项目都用 OpenAPI 3.0+。
  2. 我们在工程里把 openapi.yaml 当源代码——CI 里跑 spectral lint + openapi-diff,自动生成 SDK 发 npm,自动生成后端 Controller 接口,配合 Prism Mock 让前后端解耦。
  3. 核心要素是 components 复用——schemas / parameters / responses / securitySchemes 全抽出来,paths 里全是 $ref,加字段一处改全局生效。

把这三句背熟,你就能让面试官知道:你不只是会写文档,你懂"基于文档驱动整个工程"


觉得题目不够?欢迎在评论里贡献你遇到的真题。 学完整套笔记 → 回到 总览