2. OpenAPI 规范入门:OpenAPI 3.0 核心概念、YAML/JSON 定义、路径与操作、请求/响应模型

OpenAPI 规范(原 Swagger 规范)是描述 RESTful API 的行业标准。OpenAPI 3.0 作为当前主流版本,提供了结构化的接口定义语言,使契约测试、性能调优和故障排查有了统一的契约基础。本节将系统梳理其核心概念与表达方式。

2.1 OpenAPI 3.0 核心概念

OpenAPI 3.0 文档是一个自描述的 API 契约,包含以下核心顶层对象:

顶层对象 作用 必填
openapi 声明规范版本号(如 3.0.3) 是
info API 元信息:标题、版本、描述 是
servers API 的基础 URL 列表(支持多环境) 否
paths 所有 API 路径及操作的核心容器 是
components 可复用的 schema、参数、响应、请求体 否
tags 路径分组标签,用于文档分类 否
契约测试视角: paths 和 components 是契约测试的核心验证对象。路径定义操作契约,组件定义数据契约。性能调优时,servers 字段用于切换压测目标环境。

2.2 YAML / JSON 定义方式

OpenAPI 3.0 支持 YAML 和 JSON 两种序列化格式。YAML 因其可读性高、注释友好,成为社区首选;JSON 则更适合程序化生成和传输。

格式对比:

特性 YAML JSON
可读性 高(缩进结构、支持注释) 中(括号密集、无注释)
文件大小 较小(无冗余引号/逗号) 较大
工具生态 需注意缩进陷阱 解析严格、兼容性好
推荐场景 手写契约、代码仓库管理 API 网关、CI/CD 管道

YAML 示例(推荐):

openapi: "3.0.3"
info:
  title: 订单服务 API
  version: "1.0.0"
  description: 提供订单创建与查询能力
servers:
  - url: https://api.example.com/v1
    description: 生产环境
paths:
  /orders:
    get:
      summary: 查询订单列表
      operationId: listOrders
      parameters:
        - name: status
          in: query
          schema:
            type: string
      responses:
        '200':
          description: 成功返回订单列表
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderList'
components:
  schemas:
    Order:
      type: object
      properties:
        id:
          type: integer
        total:
          type: number
          format: float
    OrderList:
      type: array
      items:
        $ref: '#/components/schemas/Order'

JSON 等价示例:

{
  "openapi": "3.0.3",
  "info": {
    "title": "订单服务 API",
    "version": "1.0.0"
  },
  "paths": {
    "/orders": {
      "get": {
        "operationId": "listOrders",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "成功返回订单列表",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/OrderList" }
              }
            }
          }
        }
      }
    }
  }
}
常见陷阱: YAML 对缩进敏感,禁止使用 Tab 键;多行字符串使用 |(保留换行)或 >(折叠换行)。JSON 中 $ref 引用路径必须严格匹配,大小写敏感。

2.3 路径与操作

paths 对象是 API 的路由映射表。每个路径下可定义多个 HTTP 操作(method),形成完整的端点契约。

路径定义规则:

  • 静态路径: /users、/orders,直接匹配固定资源。
  • 路径参数: /users/{userId},使用花括号声明变量,在 parameters 中定义类型。
  • 操作对象: 每个路径下可包含 get、post、put、delete、patch 等。

操作对象核心字段:

字段 说明 契约测试关注点
operationId 操作的唯一标识符 用于生成测试用例名称
parameters 路径、查询、请求头参数定义 验证必填参数、参数类型
requestBody POST/PUT 的请求体描述 验证请求体结构与 content-type
responses 所有可能的 HTTP 状态码及响应结构 验证响应状态码、响应体 schema
security 操作级别的安全要求 验证鉴权 token 传递
性能调优关联: 路径参数(如 {userId})在压测时需替换为实际值;operationId 用于在性能报告中定位具体接口;parameters 中的 required 字段决定压测脚本的入参构造策略。
路径与操作结构 paths /orders /orders/{orderId} /users/{userId} GET POST GET PUT GET 说明: 每个路径下可挂载多个 HTTP 操作。路径参数(如 {orderId})在操作中通过 parameters 定义。 契约测试时,需为每个操作构造独立的请求验证用例。

2.4 请求 / 响应模型

OpenAPI 3.0 使用 requestBody 和 responses 精确描述 API 的输入输出契约。这是契约测试的核心验证对象,也是性能调优时构造压测 payload 的依据。

2.4.1 请求模型

请求模型包含三个维度:

  • 参数(parameters): 路径参数、查询参数、请求头参数。每个参数需定义 name、in(位置)、schema(类型约束)、required(是否必填)。
  • 请求体(requestBody): 用于 POST、PUT、PATCH。需声明 content.type(如 application/json)和对应的 schema。
  • 安全方案(security): 声明操作所需的认证方式(如 Bearer Token、API Key)。

请求参数定义示例:

parameters:
  - name: orderId
    in: path
    required: true
    schema:
      type: integer
      minimum: 1
  - name: pageSize
    in: query
    required: false
    schema:
      type: integer
      default: 20
      maximum: 100
requestBody:
  required: true
  content:
    application/json:
      schema:
        $ref: '#/components/schemas/CreateOrderRequest'

2.4.2 响应模型

响应模型按 HTTP 状态码组织,每个状态码对应一个响应对象:

状态码 语义 契约测试验证点
200 成功响应 响应体结构、必填字段、数据类型
201 创建成功 返回资源 ID 或 Location 头
400 请求参数错误 错误信息格式、错误码字段
401 未认证 WWW-Authenticate 头、错误体
404 资源不存在 错误描述、资源标识
500 服务端错误 是否返回通用错误结构

响应定义示例:

responses:
  '200':
    description: 订单详情
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Order'
  '404':
    description: 订单不存在
    content:
      application/json:
        schema:
          type: object
          properties:
            code:
              type: string
              example: "ORDER_NOT_FOUND"
            message:
              type: string
              example: "未找到指定订单"
性能调优关联: 响应模型中的 schema 定义了返回字段的类型和大小。在压测时,响应体大小直接影响网络传输耗时和序列化开销。大响应体(如包含嵌套数组)应作为性能瓶颈排查的切入点。
请求 / 响应数据流模型 客户端 HTTP 请求 请求参数 请求体 (requestBody) 安全凭证 服务端 HTTP 响应 状态码 + 响应体 响应头 (Headers)

2.5 组件复用与 $ref 引用

components 对象是 OpenAPI 3.0 的复用机制,避免在多个路径中重复定义相同的数据结构。契约测试中,组件定义是验证响应体结构的权威来源。

组件分类:

组件类型 用途 示例
schemas 数据模型定义(对象、数组、枚举) User、OrderList
parameters 可复用的参数定义 pageToken、locale
responses 可复用的响应结构 NotFound、Unauthorized
requestBodies 可复用的请求体定义 CreateUserBody
headers 可复用的响应头定义 X-RateLimit-Remaining

$ref 引用语法:

# 引用 schema 组件
schema:
  $ref: '#/components/schemas/Order'

# 引用参数组件
parameters:
  - $ref: '#/components/parameters/pageToken'

# 引用响应组件
responses:
  '404':
    $ref: '#/components/responses/NotFound'
契约测试注意事项: $ref 引用在解析时需注意循环引用问题。性能调优时,组件复用程度影响契约文件大小,过大的契约文件会增加解析耗时。建议将大型 schema 拆分为多个文件,使用 $ref 跨文件引用。

2.6 契约测试视角的 OpenAPI 最佳实践

  1. 显式声明所有响应状态码: 包括 4xx 和 5xx,确保契约测试覆盖异常路径。
  2. 使用 example 字段: 为每个 schema 属性提供示例值,便于自动生成测试数据。
  3. 定义 nullable 和 required: 明确字段的可空性和必填性,避免测试用例遗漏边界情况。
  4. 统一错误响应结构: 在 components/responses 中定义全局错误格式,确保所有接口的错误体一致。
  5. 标注 deprecated 操作: 弃用接口在契约中标记,性能压测时自动跳过。
性能调优提示: 在 OpenAPI 契约中为每个操作添加 x-performance-latency-sla 扩展字段,标注该接口的预期 P99 延迟阈值。压测工具可读取该字段自动判断性能是否达标。