Skip to content

Latest commit

 

History

History
718 lines (630 loc) · 15.5 KB

File metadata and controls

718 lines (630 loc) · 15.5 KB

OpenAPI 规范详解

OpenAPI Specification (OAS) 是一个用于描述 RESTful API 的标准规范,前身是 Swagger 规范。

📚 目录

  1. 什么是 OpenAPI
  2. OpenAPI 文档结构
  3. 核心组件详解
  4. 实际应用示例
  5. 在当前项目中的应用

什么是 OpenAPI

OpenAPI 是一个机器可读的接口文档规范,它使用 JSON 或 YAML 格式来描述 API:

  • 版本: OpenAPI 3.0.x(目前主流)或 2.0(Swagger)
  • 作用: 描述 API 的路径、方法、参数、响应等
  • 好处:
    • 自动生成客户端代码
    • 自动生成文档
    • 自动生成 Mock 数据
    • API 测试工具集成

OpenAPI 文档结构

基本结构

{
  "openapi": "3.0.0",        // OpenAPI 版本
  "info": { },                // API 基本信息
  "servers": [ ],             // 服务器地址
  "paths": { },               // API 路径定义
  "components": { },          // 可复用组件
  "security": [ ],            // 安全定义
  "tags": [ ],                // 标签分组
  "externalDocs": { }         // 外部文档
}

1. Info - API 基本信息

{
  "info": {
    "title": "Swagger Petstore",           // API 名称
    "description": "宠物商店 API",         // API 描述
    "version": "1.0.0",                    // API 版本
    "contact": {                           // 联系信息
      "email": "apiteam@swagger.io"
    },
    "license": {                           // 许可证
      "name": "Apache 2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
    }
  }
}

2. Servers - 服务器地址

定义 API 的服务器地址:

{
  "servers": [
    {
      "url": "https://petstore3.swagger.io/api/v3",
      "description": "生产环境"
    },
    {
      "url": "http://localhost:8080/api/v3",
      "description": "开发环境"
    }
  ]
}

3. Paths - API 路径定义(核心)

定义所有的 API 端点:

{
  "paths": {
    "/pet": {
      "post": {              // HTTP 方法
        "summary": "添加宠物",
        "operationId": "addPet",
        "tags": ["pet"],
        "requestBody": { },
        "responses": { }
      },
      "get": { },
      "put": { }
    },
    "/pet/{petId}": {        // 路径参数
      "get": {
        "summary": "根据 ID 获取宠物",
        "parameters": [
          {
            "name": "petId",
            "in": "path",     // 参数位置: path, query, header, cookie
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ]
      }
    }
  }
}

路径参数

  • {petId} - 在 URL 路径中的参数
  • 使用 parameters 数组定义,in: "path"

查询参数

{
  "name": "status",
  "in": "query",
  "schema": {
    "type": "string",
    "enum": ["available", "pending", "sold"]
  }
}

4. Operation - 操作定义

每个 HTTP 方法包含一个 operation 对象:

{
  "get": {
    "summary": "获取宠物列表",           // 简短描述
    "description": "根据状态筛选宠物",   // 详细描述
    "operationId": "findPetsByStatus",   // 操作唯一标识
    "tags": ["pet"],                     // 标签分组
    "parameters": [ ],                   // 参数列表
    "requestBody": { },                  // 请求体(POST/PUT)
    "responses": { },                    // 响应定义
    "security": [ ],                     // 安全要求
    "deprecated": false                  // 是否已废弃
  }
}

Parameters - 参数定义

参数可以在路径、查询、header、cookie 中:

{
  "parameters": [
    {
      "name": "petId",                    // 参数名
      "in": "path",                       // 位置: path, query, header, cookie
      "description": "宠物 ID",
      "required": true,                   // 是否必需
      "schema": {
        "type": "integer",
        "format": "int64"
      }
    },
    {
      "name": "status",
      "in": "query",
      "description": "宠物状态",
      "required": false,
      "schema": {
        "type": "string",
        "enum": ["available", "pending", "sold"]
      }
    }
  ]
}

参数位置 (in)

  • path - URL 路径中,如 /pet/{petId}
  • query - URL 查询字符串,如 ?status=available
  • header - HTTP 头,如 Authorization: Bearer token
  • cookie - Cookie 中

RequestBody - 请求体

用于 POST、PUT、PATCH 请求:

{
  "requestBody": {
    "description": "要添加的宠物对象",
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/Pet"
        }
      },
      "application/xml": {
        "schema": {
          "$ref": "#/components/schemas/Pet"
        }
      }
    }
  }
}

Content Types

  • application/json - JSON 格式
  • application/xml - XML 格式
  • multipart/form-data - 文件上传
  • application/x-www-form-urlencoded - 表单提交

Responses - 响应定义

定义 API 的响应:

{
  "responses": {
    "200": {                              // HTTP 状态码
      "description": "成功返回宠物列表",
      "content": {
        "application/json": {
          "schema": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Pet"
            }
          }
        }
      }
    },
    "400": {
      "description": "无效的请求",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "500": {
      "$ref": "#/components/responses/ServerError"
    }
  }
}

5. Components - 可复用组件

存放可复用的定义:

{
  "components": {
    "schemas": { },          // 数据模型(类型定义)
    "responses": { },        // 响应定义
    "parameters": { },       // 参数定义
    "examples": { },         // 示例
    "requestBodies": { },    // 请求体定义
    "headers": { },          // 请求头定义
    "securitySchemes": { }   // 安全方案
  }
}

Schemas - 数据模型

定义数据结构和类型:

{
  "components": {
    "schemas": {
      "Pet": {
        "type": "object",
        "required": ["name", "photoUrls"],  // 必需字段
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "example": 10
          },
          "name": {
            "type": "string",
            "example": "doggie"
          },
          "category": {
            "$ref": "#/components/schemas/Category"  // 引用其他 schema
          },
          "photoUrls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "status": {
            "type": "string",
            "enum": ["available", "pending", "sold"],  // 枚举值
            "description": "宠物状态"
          }
        }
      }
    }
  }
}

数据类型 (type)

  • string - 字符串
  • number - 数字(浮点数)
  • integer - 整数
  • boolean - 布尔值
  • array - 数组
  • object - 对象

格式 (format)

  • int32, int64 - 整数位数
  • float, double - 浮点数精度
  • date, date-time - 日期格式
  • email, uri, uuid - 特殊格式

引用 ($ref): 使用 $ref 引用其他组件,避免重复定义:

{
  "$ref": "#/components/schemas/Pet"      // 引用 Pet schema
}

组合类型

{
  "allOf": [                               // 合并多个 schema
    { "$ref": "#/components/schemas/Base" },
    {
      "type": "object",
      "properties": {
        "extension": { "type": "string" }
      }
    }
  ],
  "oneOf": [                               // 多个 schema 之一
    { "$ref": "#/components/schemas/Cat" },
    { "$ref": "#/components/schemas/Dog" }
  ],
  "anyOf": [ ],                            // 任意匹配
  "not": { }                               // 排除
}

Security Schemes - 安全方案

定义认证方式:

{
  "components": {
    "securitySchemes": {
      "api_key": {
        "type": "apiKey",
        "name": "api_key",
        "in": "header"
      },
      "petstore_auth": {
        "type": "oauth2",
        "flows": {
          "implicit": {
            "authorizationUrl": "https://petstore3.swagger.io/oauth/authorize",
            "scopes": {
              "write:pets": "修改宠物",
              "read:pets": "读取宠物"
            }
          }
        }
      }
    }
  }
}

6. Tags - 标签分组

用于对 API 进行分组:

{
  "tags": [
    {
      "name": "pet",
      "description": "宠物相关操作"
    },
    {
      "name": "store",
      "description": "商店相关操作"
    }
  ]
}

实际应用示例

完整的 API 定义示例

{
  "openapi": "3.0.0",
  "info": {
    "title": "宠物商店 API",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://api.example.com/v3"
    }
  ],
  "paths": {
    "/pet/{petId}": {
      "get": {
        "summary": "获取宠物详情",
        "operationId": "getPetById",
        "tags": ["pet"],
        "parameters": [
          {
            "name": "petId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pet"
                }
              }
            }
          },
          "404": {
            "description": "宠物不存在"
          }
        }
      },
      "delete": {
        "summary": "删除宠物",
        "operationId": "deletePet",
        "tags": ["pet"],
        "parameters": [
          {
            "name": "petId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "api_key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "删除成功"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/pet/findByStatus": {
      "get": {
        "summary": "根据状态查找宠物",
        "operationId": "findPetsByStatus",
        "tags": ["pet"],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": ["available", "pending", "sold"],
              "default": "available"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Pet"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/pet": {
      "post": {
        "summary": "添加新宠物",
        "operationId": "addPet",
        "tags": ["pet"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Pet"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "成功"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Pet": {
        "type": "object",
        "required": ["name", "photoUrls"],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "type": "string",
            "example": "doggie"
          },
          "status": {
            "type": "string",
            "enum": ["available", "pending", "sold"]
          },
          "photoUrls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "api_key": {
        "type": "apiKey",
        "name": "api_key",
        "in": "header"
      }
    }
  }
}

在当前项目中的应用

1. 代码生成器如何解析 OpenAPI

查看 bin/index.js 中的实现:

// 1. 读取 paths
let paths = openapiJson.paths;
for (const path in paths) {
  let methods = paths[path];  // get, post, put, delete
  
  // 2. 读取每个 HTTP 方法
  for (const method in methods) {
    let operation = methods[method];
    
    // 3. 提取 operation 信息
    let operationId = operation.operationId;
    let parameters = operation.parameters || [];
    let requestBody = operation.requestBody;
    let responses = operation.responses;
    let tags = operation.tags;
  }
}

2. 当前支持的 OpenAPI 特性

已支持

  • 基本路径和方法定义
  • Path 参数(in: "path"
  • Query 参数(in: "query"
  • Request Body
  • Response Schema
  • Schema 引用($ref
  • 数组类型
  • 基本类型(string, number, boolean, integer)
  • Tags 分组

暂不支持

  • Enum(枚举)→ 应生成 union 类型
  • Required 字段 → 应生成必需属性(非可选)
  • Nullable → 应支持 string | null
  • Format(date-time 等)→ 应处理特殊格式
  • allOf/oneOf/anyOf → 组合类型
  • additionalProperties → 索引签名
  • Header 参数(目前混在 query 中)
  • Cookie 参数
  • Security 定义的应用

3. 扩展字段的使用

OpenAPI 允许使用 x-* 扩展字段添加自定义配置:

{
  "paths": {
    "/pet/{petId}": {
      "get": {
        "operationId": "getPetById",
        "x-openapi-cli": {
          "timeout": 5000,
          "retry": 3,
          "cache": true
        }
      }
    }
  }
}

这些扩展字段可以被代码生成器读取和应用。


最佳实践

1. 命名规范

  • operationId: 使用驼峰命名,唯一且有意义
  • 路径: 使用 RESTful 风格,如 /pet/{petId}
  • Tag: 使用名词复数,如 pets, orders

2. 参数设计

  • Path 参数:用于资源标识,如 /pet/{petId}
  • Query 参数:用于筛选、分页、排序
  • Request Body:用于复杂对象传递(POST/PUT)

3. 响应设计

  • 定义所有可能的 HTTP 状态码
  • 使用 Schema 引用避免重复
  • 提供清晰的错误响应格式

4. 类型定义

  • 将常用类型定义在 components.schemas
  • 使用 $ref 引用,避免重复
  • 充分利用 enum、required、format

参考资料


总结

OpenAPI 规范是一个强大的工具,它:

  • 📝 提供结构化的 API 文档
  • 🤖 支持自动化代码生成
  • 🧪 支持 API 测试和 Mock
  • 🔄 实现前后端协作标准化

在当前项目中,我们利用 OpenAPI 规范自动生成 TypeScript 接口代码,大大提高了开发效率!