OpenAPI 规范基础

OpenAPI 规范(OAS)是一种用于描述 RESTful API 的标准格式。

OpenAPI 规范允许开发者以机器可读的方式定义 API 的结构、参数、响应等信息。

OpenAPI 规范最初被称为 Swagger 规范,后来被捐赠给 OpenAPI Initiative 并更名为 OpenAPI。

OpenAPI 规范的主要作用包括:

  • 提供 API 的标准化文档
  • 支持 API 的自动化测试
  • 生成客户端 SDK
  • 促进前后端分离开发

OpenAPI 目前主要有两个广泛使用的版本:

  1. OpenAPI 2.0(原 Swagger 2.0)
  2. OpenAPI 3.x(最新稳定版本)

建议新项目使用 OpenAPI 3.x 版本,因为它提供了更多功能和改进。

OpenAPI 规范的结构

OpenAPI 文档通常以 YAML 或 JSON 格式编写。

下面是一个基本的 OpenAPI 文档结构:

实例

openapi: 3.1.0           # OpenAPI 版本
info:
  title: 示例 API         # API 名称
  description: 这是一个示例 API 文档
  version: 1.0.0         # API 版本
servers:
  - url: https://api.example.com/v1  # API 服务器地址
    description: 生产环境
  - url: https://dev-api.example.com/v1
    description: 开发环境

paths:                   # API 路径定义
  /users:                # 端点路径
    get:                 # HTTP 方法
      summary: 获取所有用户
      description: 返回系统中的所有用户列表
      operationId: getUsers
      tags:
        - users          # 分组标签
      parameters:        # 请求参数
        - name: limit
          in: query
          description: 返回结果数量限制
          schema:
            type: integer
            default: 20
      responses:         # 响应定义
        '200':           # HTTP 状态码
          description: 成功返回用户列表
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
        '400':
          description: 错误的请求参数

components:              # 可复用组件
  schemas:               # 数据模型定义
    User:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        email:
          type: string
          format: email
      required:
        - id
        - name

OpenAPI 核心概念详解

1. 文档元数据 (info)

info 部分包含 API 的基本信息,如标题、描述、版本等:

实例

info:
  title: 用户管理 API
  description: API 用于管理系统中的用户信息
  version: 1.0.0
  contact:
    name: API 支持团队
    email: support@example.com
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html

2. 服务器信息 (servers)

servers 部分定义可用的 API 服务器列表:

实例

servers:
  - url: https://api.example.com/v1
    description: 生产环境
  - url: https://staging-api.example.com/v1
    description: 测试环境

3. 路径 (paths)

paths 部分定义 API 的所有端点和它们支持的 HTTP 方法:

实例

paths:
  /users:
    get:
      # 获取用户列表
    post:
      # 创建新用户
  /users/{userId}:
    get:
      # 获取特定用户
    put:
      # 更新用户
    delete:
      # 删除用户

4. 操作 (operations)

每个路径下的 HTTP 方法定义了一个 API 操作:

实例

paths:
  /users/{userId}:
    get:
      summary: 获取用户详情
      description: 根据用户ID获取用户的详细信息
      operationId: getUserById
      tags:
        - users
      parameters:
        - name: userId
          in: path
          required: true
          description: 用户ID
          schema:
            type: integer
      responses:
        '200':
          description: 成功获取用户信息
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          description: 用户不存在
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

5. 参数 (parameters)

参数可以定义在多个位置:

实例

parameters:
  - name: userId
    in: path           # 路径参数
    required: true
    schema:
      type: integer
  - name: filter
    in: query          # 查询参数
    schema:
      type: string
  - name: X-API-Key
    in: header         # 请求头参数
    schema:
      type: string
  - name: trace
    in: cookie         # Cookie参数
    schema:
      type: string

6. 请求体 (requestBody)

定义 POST、PUT 等方法的请求体:

实例

requestBody:
  description: 用户数据
  required: true
  content:
    application/json:
      schema:
        $ref: '#/components/schemas/User'
    application/x-www-form-urlencoded:
      schema:
        $ref: '#/components/schemas/UserForm'

7. 响应 (responses)

定义每个操作可能的响应:

实例

responses:
  '200':
    description: 操作成功
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/SuccessResponse'
  '400':
    description: 请求参数错误
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/ErrorResponse'

8. 组件 (components)

components 部分用于存储可在整个 API 文档中重用的元素:

实例

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        email:
          type: string
          format: email
        roles:
          type: array
          items:
            type: string
            enum: [admin, user, editor]
      required:
        - name
        - email
   
    Error:
      type: object
      properties:
        code:
          type: integer
        message:
          type: string
      required:
        - code
        - message
 
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
   
    OAuth2:
      type: oauth2
      flows:
        implicit:
          authorizationUrl: https://example.com/oauth/authorize
          scopes:
            read: 读取权限
            write: 写入权限

9. 数据模型 (schemas)

定义 API 中使用的数据结构:

实例

schemas:
  Product:
    type: object
    properties:
      id:
        type: integer
      name:
        type: string
        maxLength: 100
      price:
        type: number
        format: float
        minimum: 0
      category:
        type: string
        enum: [electronics, books, clothing]

10. 安全 (security)

定义 API 的认证和授权方法:

实例

security:
  - ApiKeyAuth: []
  - OAuth2: [read, write]

创建完整的 OpenAPI 文档实例

下面是一个更完整的电子商务 API 示例:

实例

openapi: 3.1.0
info:
  title: 电子商务 API
  description: 用于管理在线商店的产品和订单的 API
  version: 1.0.0
  contact:
    name: API 支持团队
    email: support@example.com
    url: https://api.example.com/support
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: https://api.example.com/v1
    description: 生产环境
  - url: https://dev-api.example.com/v1
    description: 开发环境

tags:
  - name: products
    description: 产品相关操作
  - name: orders
    description: 订单相关操作
  - name: users
    description: 用户相关操作

paths:
  /products:
    get:
      summary: 获取产品列表
      description: 返回所有可用产品的列表,支持分页和过滤
      operationId: getProducts
      tags:
        - products
      parameters:
        - name: category
          in: query
          description: 按产品类别过滤
          schema:
            type: string
        - name: page
          in: query
          description: 页码
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          description: 每页数量
          schema:
            type: integer
            default: 20
      responses:
        '200':
          description: 成功获取产品列表
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                  products:
                    type: array
                    items:
                      $ref: '#/components/schemas/Product'
        '400':
          description: 参数错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
   
    post:
      summary: 创建新产品
      description: 创建新的产品信息
      operationId: createProduct
      tags:
        - products
      security:
        - ApiKeyAuth: []
        - OAuth2: [write]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProductCreate'
      responses:
        '201':
          description: 产品创建成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '400':
          description: 无效的请求数据
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: 未授权
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /products/{productId}:
    get:
      summary: 获取产品详情
      description: 根据ID获取特定产品的详细信息
      operationId: getProductById
      tags:
        - products
      parameters:
        - name: productId
          in: path
          required: true
          description: 产品ID
          schema:
            type: integer
      responses:
        '200':
          description: 成功获取产品信息
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '404':
          description: 产品不存在
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
   
    put:
      summary: 更新产品
      description: 更新特定产品的信息
      operationId: updateProduct
      tags:
        - products
      security:
        - ApiKeyAuth: []
        - OAuth2: [write]
      parameters:
        - name: productId
          in: path
          required: true
          description: 产品ID
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProductUpdate'
      responses:
        '200':
          description: 产品更新成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '400':
          description: 无效的请求数据
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: 未授权
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: 产品不存在
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
   
    delete:
      summary: 删除产品
      description: 删除特定的产品
      operationId: deleteProduct
      tags:
        - products
      security:
        - ApiKeyAuth: []
        - OAuth2: [write]
      parameters:
        - name: productId
          in: path
          required: true
          description: 产品ID
          schema:
            type: integer
      responses:
        '204':
          description: 产品删除成功
        '401':
          description: 未授权
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: 产品不存在
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /orders:
    get:
      summary: 获取订单列表
      description: 返回所有订单的列表,支持分页和过滤
      operationId: getOrders
      tags:
        - orders
      security:
        - ApiKeyAuth: []
        - OAuth2: [read]
      parameters:
        - name: status
          in: query
          description: 按订单状态过滤
          schema:
            type: string
            enum: [pending, processing, shipped, delivered, cancelled]
        - name: page
          in: query
          description: 页码
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          description: 每页数量
          schema:
            type: integer
            default: 20
      responses:
        '200':
          description: 成功获取订单列表
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                  orders:
                    type: array
                    items:
                      $ref: '#/components/schemas/Order'
        '401':
          description: 未授权
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
   
    post:
      summary: 创建新订单
      description: 创建新的订单
      operationId: createOrder
      tags:
        - orders
      security:
        - ApiKeyAuth: []
        - OAuth2: [write]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OrderCreate'
      responses:
        '201':
          description: 订单创建成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
        '400':
          description: 无效的请求数据
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: 未授权
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

components:
  schemas:
    Product:
      type: object
      properties:
        id:
          type: integer
          format: int64
          readOnly: true
        name:
          type: string
          maxLength: 100
        description:
          type: string
        price:
          type: number
          format: float
          minimum: 0
        category:
          type: string
          enum: [electronics, books, clothing, food]
        inStock:
          type: boolean
          default: true
        createdAt:
          type: string
          format: date-time
          readOnly: true
        updatedAt:
          type: string
          format: date-time
          readOnly: true
      required:
        - name
        - price
        - category
   
    ProductCreate:
      type: object
      properties:
        name:
          type: string
          maxLength: 100
        description:
          type: string
        price:
          type: number
          format: float
          minimum: 0
        category:
          type: string
          enum: [electronics, books, clothing, food]
        inStock:
          type: boolean
          default: true
      required:
        - name
        - price
        - category
   
    ProductUpdate:
      type: object
      properties:
        name:
          type: string
          maxLength: 100
        description:
          type: string
        price:
          type: number
          format: float
          minimum: 0
        category:
          type: string
          enum: [electronics, books, clothing, food]
        inStock:
          type: boolean
   
    Order:
      type: object
      properties:
        id:
          type: integer
          format: int64
          readOnly: true
        userId:
          type: integer
          format: int64
        items:
          type: array
          items:
            $ref: '#/components/schemas/OrderItem'
        totalAmount:
          type: number
          format: float
          readOnly: true
        status:
          type: string
          enum: [pending, processing, shipped, delivered, cancelled]
          default: pending
        shippingAddress:
          $ref: '#/components/schemas/Address'
        createdAt:
          type: string
          format: date-time
          readOnly: true
        updatedAt:
          type: string
          format: date-time
          readOnly: true
      required:
        - userId
        - items
        - shippingAddress
   
    OrderCreate:
      type: object
      properties:
        userId:
          type: integer
          format: int64
        items:
          type: array
          items:
            $ref: '#/components/schemas/OrderItem'
        shippingAddress:
          $ref: '#/components/schemas/Address'
      required:
        - userId
        - items
        - shippingAddress
   
    OrderItem:
      type: object
      properties:
        productId:
          type: integer
          format: int64
        quantity:
          type: integer
          minimum: 1
          default: 1
        unitPrice:
          type: number
          format: float
          readOnly: true
      required:
        - productId
        - quantity
   
    Address:
      type: object
      properties:
        street:
          type: string
        city:
          type: string
        state:
          type: string
        zipCode:
          type: string
        country:
          type: string
      required:
        - street
        - city
        - state
        - zipCode
        - country
   
    Error:
      type: object
      properties:
        code:
          type: integer
        message:
          type: string
      required:
        - code
        - message
 
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
   
    OAuth2:
      type: oauth2
      flows:
        implicit:
          authorizationUrl: https://example.com/oauth/authorize
          scopes:
            read: 读取权限
            write: 写入权限

security:
  - ApiKeyAuth: []

OpenAPI 规范的基本语法

OpenAPI 规范支持两种格式:

  1. YAML(推荐)
  2. JSON

YAML 格式示例

实例

openapi: 3.0.0
info:
  title: 宠物商店 API
  version: 1.0.0
paths:
  /pets:
    get:
      summary: 列出所有宠物
      responses:
        '200':
          description: 成功获取宠物列表

JSON 格式示例

实例

"openapi": "3.0.0",
  "info": {
    "title": "宠物商店 API",
    "version": "1.0.0"
  },
  "paths": {
    "/pets": {
      "get": {
        "summary": "列出所有宠物",
        "responses": {
          "200": {
            "description": "成功获取宠物列表"
          }
        }
      }
    }
  }
}

如何使用 OpenAPI 规范

1. 创建和编辑 OpenAPI 文档

可以使用以下工具创建和编辑 OpenAPI 文档:

  • Swagger Editor:在线编辑器,提供实时预览和验证
  • Stoplight Studio:可视化 API 设计工具
  • VS Code + OpenAPI 插件:集成开发环境中编辑

2. 文档生成

使用 OpenAPI 规范可以自动生成美观的 API 文档,常用工具包括:

  • Swagger UI:生成交互式 API 文档
  • ReDoc:提供响应式、可自定义的文档
  • Slate:生成优雅的静态文档

3. 代码生成

OpenAPI 可以自动生成多种语言的客户端和服务器代码:

  • OpenAPI Generator:支持 40+ 种编程语言
  • Swagger Codegen:生成客户端和服务器代码
  • NSwag:针对 .NET 生态系统的代码生成器

4. API 测试和模拟

OpenAPI 规范还可用于:

  • 自动化测试:使用 Postman、SoapUI 等工具
  • API 模拟:Prism、Microcks 等可以基于 OpenAPI 规范模拟 API

最佳实践

1. 设计原则

  • 保持端点命名一致
  • 使用合适的 HTTP 方法和状态码
  • 设计清晰的 URL 路径结构

2. 文档建议

  • 提供详细的描述和示例
  • 使用标签对 API 进行分组
  • 明确指定必填参数

3. 版本控制策略

  • 在 URL 中包含版本号(/v1/users
  • 使用请求头指定版本(Accept: application/vnd.example.v1+json
  • 在 OpenAPI 文档中明确版本信息

常见问题解答

1. OpenAPI 与 Swagger 的区别?

Swagger 是 OpenAPI 规范的前身。2016 年,Swagger 规范被捐赠给 Linux 基金会并重命名为 OpenAPI 规范。现在,"Swagger" 通常指的是围绕 OpenAPI 规范构建的工具集。

2. OpenAPI 2.0 和 3.x 的主要区别?

OpenAPI 3.x 引入了许多新功能,包括:

  • 改进的组件重用
  • 更灵活的请求体定义
  • 更强大的安全定义
  • 改进的 JSON Schema 支持
  • links(链接)和 callbacks(回调)支持

3. 如何处理认证和授权?

OpenAPI 支持多种安全机制:

  • API 密钥
  • HTTP 基本认证
  • OAuth2.0
  • OpenID Connect
  • 自定义头认证

学习资源

  1. 官方文档:OpenAPI Initiative
  2. 工具:
  3. 学习资源: