CC 咖啡猫的工作空间 Coding Space

API 入门与设计

原始素材:4-服务器与后端/4.08-api-intro.md

什么是 API? 这就像问:餐厅的菜单怎么设计,客人一看就懂?服务员怎么记单,不会出错?API 解决的就是"程序之间如何对话"的问题。你写代码的第一天就在用 API,只是你可能没意识到。

0. 新手常见的三个困惑

困惑一:API 是很高深的东西吗?

很多人一听到 API,就觉得是高级工程师才能理解的概念。其实你早就用过 API 了:


len("hello")        # 这就是 Python 提供的 API
open("file.txt")    # 这也是 API
requests.get(url)   # 这还是 API

困惑二:Web API 和普通 API 有什么区别?

类型 调用对象 通信方式 典型场景
函数 API 本地代码 函数调用 len(), open()
操作系统 API 操作系统 系统调用 读写文件、创建进程
Web API 远程服务器 HTTP 请求 调用 AI 模型、获取天气

困惑三:我该用 HTTP 还是 SDK?


import requests
response = requests.post(
    "https://api.deepseek.com/v1/chat/completions",
    headers={"Authorization": "Bearer sk-xxx"},
    json={"model": "deepseek-chat", "messages": [...]}
)
result = response.json()["choices"][0]["message"]["content"]

from openai import OpenAI
client = OpenAI(api_key="sk-xxx")
response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[...]
)
result = response.choices[0].message.content

1. API 的本质:插头与插座

API(Application Programming Interface,应用程序编程接口)就是"程序之间对话的约定"。

1.1 用电器来类比

概念 电器类比 API 对应
接口 插座形状 函数签名 / URL
输入 电流输入 函数参数 / 请求体
输出 电器工作 返回值 / 响应体

1.2 三种 API 形态对比

调用对象本地代码库

通信方式函数调用

延迟纳秒级

典型场景数据处理、文件操作

函数 API 示例

len("hello")           # 返回 5
max([1, 5, 3])         # 返回 5
open("file.txt").read() # 读取文件

1.3 函数 API vs HTTP API 的区别

很多初学者会困惑:函数 API 和 HTTP API 到底有什么区别?看文档时该如何区分?

维度 函数 API(本地) HTTP API(远程)
调用方式 直接函数调用 网络请求
参数传递 括号内传参 URL / Body / Header
返回值 直接获得结果 JSON / XML 响应
错误处理 异常 / 返回值 HTTP 状态码判断

函数 API 示例:

# 调用内置函数
length = len("hello")      # 返回 5

# 调用库函数
import math
result = math.sqrt(16)     # 返回 4.0

# 调用自定义函数
def add(a, b):
    return a + b
sum = add(3, 5)            # 返回 8

HTTP API 示例:

POST /v1/chat/completions HTTP/1.1
Host: api.deepseek.com
Authorization: Bearer sk-xxx
Content-Type: application/json

{"model": "deepseek-chat", "messages": [{"role": "user", "content": "你好"}]}

核心要点: 函数 API 是"本地办事",HTTP API 是"远程通信"。看文档时,函数关注参数和返回值,HTTP API 关注 Endpoint、认证和请求/响应格式。

1.4 不同类型的 API 文档怎么看

面对不同类型的 API 文档,关注重点各不相同:

维度 函数文档 REST API 文档 SDK 文档
适用场景 使用标准库/第三方库函数 调用远程服务 使用厂商 SDK
阅读难度 ⭐⭐ ⭐⭐⭐ ⭐⭐
核心关注 参数、返回值 Endpoint、请求体 初始化、方法链
代码示例 函数调用 HTTP 请求 对象方法
错误处理 异常/返回值 状态码 异常对象
先看什么 函数签名 Base URL + Auth Quick Start

函数文档示例

### json.loads(s, *, cls=None, object_hook=None...)

将 JSON 字符串解析为 Python 对象

**参数:**
- s (str): 要解析的 JSON 字符串
- cls (JSONDecoder): 自定义解码器类
- object_hook (callable): 可选的转换函数

**返回值:**
- dict | list: 解析后的 Python 对象

**异常:**
- JSONDecodeError: 字符串格式非法

**示例:**
>>> import json
>>> json.loads('{"name": "Alice"}')
{'name': 'Alice'}

阅读建议

  • 先看函数签名,了解需要什么参数
  • 注意参数的类型和是否必填
  • 查看返回值类型,方便后续处理
  • 关注可能抛出的异常,做好错误处理

阅读建议 :函数文档看签名,API 文档看请求格式,SDK 文档看示例。遇到不会的,先找「Quick Start」或「Getting Started」章节。

2. 一次完整的 API 调用

API 调用演示:选择端点 GET /api/users | POST /api/users | GET /api/users/999 | POST /api/ordersHTTP Request → 等待中... → HTTP Response

2.1 API 调用的四个阶段

阶段 发生了什么 电器类比
请求 客户端向服务器发送请求 按下开关
传输 请求通过网络传输到服务器 电流通过电线
处理 服务器处理请求并返回数据 电器开始工作
响应 客户端接收并处理返回结果 灯泡发光

2.2 餐厅类比

餐厅角色 API 对应 说明
菜单 API 文档 告诉你有哪些"菜"可以点
服务员 HTTP 协议 标准化的"对话方式"
后厨 服务端 按"订单"处理请求
上菜 响应 把结果返回给"客人"

3. HTTP 方法:你是在"问"还是在"做"?

调用 Web API 时,你需要告诉服务器你想做什么。这就是 HTTP 方法的由来。

3.1 用餐厅点餐来理解

场景 现实中你会怎么说? 对应的 HTTP 方法
你想知道今天有什么菜 "服务员,菜单给我看看" GET - 纯"问",不改数据
你想点一份宫保鸡丁 "给我来份宫保鸡丁" POST - "做"件事,创建数据
你想换一道菜 "把宫保鸡丁改成糖醋里脊" PUT - 替换数据
你想改口味 "宫保鸡丁不要放花生" PATCH - 部分修改
你不想要了 "算了,那道菜不要了" DELETE - 删除数据

关于幂等性

幂等性 :多次执行结果是否相同?

  • 幂等的操作(GET/PUT/DELETE):点 10 次和点 1 次,结果一样
  • 不幂等的操作(POST):点 10 次,可能创建 10 个订单

解决方案 :POST 操作用唯一 ID 校验,避免重复处理。

3.2 HTTP 方法速查表

方法 用途 幂等性 安全性 典型场景
POST 创建资源 新增用户、提交订单
PUT 全量更新 替换整个用户资料
PATCH 部分更新 只修改昵称
DELETE 删除资源 删除用户、取消订单

4. HTTP 状态码:服务器在告诉你什么?

服务器回复时,会先返回一个状态码,告诉你请求是否成功。

4.1 状态码分类

分类 含义 典型状态码
2xx 成功 - 请求被成功接收、理解并处理 200 OK, 201 Created, 204 No Content
3xx 重定向 - 需要进一步操作才能完成请求 301 永久移动, 304 未修改, 307 临时重定向
4xx 客户端错误 - 请求包含错误或无法完成 400 参数错误, 401 未认证, 403 无权限, 404 不存在
5xx 服务器错误 - 服务器无法处理有效请求 500 内部错误, 502 网关错误, 503 服务不可用

4.2 常见状态码详解

状态码 含义 典型场景 客户端处理
200 OK 成功 请求正常处理 展示数据
201 Created 创建成功 POST 请求成功创建资源 跳转到新资源
400 Bad Request 请求格式错误 参数缺失或格式不对 检查参数
401 Unauthorized 未认证 没有提供有效的 API Key 引导用户登录
403 Forbidden 无权限 API Key 没有访问该资源的权限 提示权限不足
404 Not Found 不存在 请求的地址或资源不存在 检查 URL
429 Too Many Requests 请求过多 超过了速率限制 稍后重试
500 Internal Server Error 服务器错误 服务端出了问题 提示用户稍后重试

快速参考表

分类 状态码 含义
✅ 成功 200 OK - 请求成功
201 Created - 创建成功
204 No Content - 无返回内容
⚠️ 客户端错误 400 Bad Request - 请求格式错误
401 Unauthorized - 未认证
403 Forbidden - 无权限
404 Not Found - 资源不存在
422 Unprocessable - 语义错误
429 Too Many - 请求过多
❌ 服务器错误 500 Server Error - 内部错误
502 Bad Gateway - 网关错误
503 Unavailable - 服务不可用

5. HTTP vs SDK:自己跑腿还是让管家代办?

5.1 两种调用方式对比

维度 🏃 HTTP API(直接请求) 🤵 SDK(封装调用)
比喻 自己跑腿 管家代办
优点 ✓ 所有语言都能用 / ✓ 完全控制请求细节 / ✓ 无需额外依赖 ✓ 代码简洁易读 / ✓ 自动处理鉴权 / ✓ 内置错误重试
缺点 ✗ 需要处理所有细节 / ✗ 代码冗长易出错 ✗ 需要安装依赖 / ✗ 可能有版本问题
代码示例 requests.post(url, json=..., headers={...}) client.chat.completions.create(...)

5.2 如何选择?

场景 推荐方式 原因
快速开发 SDK 自动处理鉴权、错误、重试
学习原理 HTTP 理解底层机制
不支持的语言 HTTP 任何语言都能用
需要定制 HTTP 灵活控制每个细节

能用 SDK 就用 SDK ,把麻烦事留给库,把时间留给自己。

6. 如何阅读 API 文档?

API 文档就像说明书和菜单的结合体。你不需要从头读到尾,只需要学会"查字典"。

6.1 文档阅读清单

打开任何一个 API 文档(如 OpenAI 或 DeepSeek),你只需要找这几样东西:

要素 说明
Base URL https://api.deepseek.com API 服务地址
Endpoint POST /v1/chat/completions 接口路径 + 方法
Headers Authorization: Bearer sk-xxx / Content-Type: application/json 鉴权 + 内容类型
Body 参数 model(必填)、messages(必填)、temperature(可选,0-2,默认 1) 请求体字段

翻译成代码:

from openai import OpenAI

client = OpenAI(
    api_key="sk-xxx",
    base_url="https://api.deepseek.com"
)

response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[{"role": "user", "content": "你好"}]
)

核心思想: 看文档找三样:地址(Base URL)、鉴权(Authorization)、参数(Parameters)。

项目 说明 示例
Base URL API 的根地址 https://api.deepseek.com
Authentication 如何证明身份 Authorization: Bearer sk-xxx
Endpoints 具体的接口列表 /v1/chat/completions
Parameters 必填/可选参数 model(必填)、temperature(可选)
Response 返回数据结构 {"choices": [...]}

6.2 阅读文档的步骤

  1. 找到 Base URL - 这是所有请求的前缀
  2. 看懂认证方式 - API Key 放在 Header 还是 Query?
  3. 找到需要的 Endpoint - 你要调用的具体接口
  4. 查看请求参数 - 哪些必填?哪些可选?
  5. 理解返回格式 - 数据是如何组织的?

Endpoint

方法

GETPOSTPUTDELETE

API Key

试着触发以下场景:

  • 成功请求 :填入正确的 Endpoint 和 API Key
  • 404 错误 :填一个不存在的地址

8. 小结

核心要点

  1. API 就是传声筒 ,帮你把话传给另一段代码或远程服务器
  2. 你早就用过 API 了 ,从 len()open() 都是 API
  3. Web API 是超能力 ,让你调用千里之外的超级电脑
  4. SDK 是好管家 ,能用 SDK 就别自己跑腿
  5. 看文档找三样 :地址、鉴权、参数

在 AI 编程的时代,你只需要记住这几个核心概念。剩下的细节,IDE 和 AI 助手会帮你处理。

名词速查表

名词 全称 解释
API Application Programming Interface 应用程序编程接口,定义了软件之间如何交互
Web API - 基于 HTTP 协议的 API,用于网络通信
Endpoint - 端点,API 的具体地址
HTTP HyperText Transfer Protocol Web API 使用的通信协议
GET - 获取资源的方法
POST - 提交数据的方法
SDK Software Development Kit 软件开发工具包,封装了底层 API 调用
URL Uniform Resource Locator API 的网络地址
JSON JavaScript Object Notation 常用的数据格式
Authentication - 验证身份的过程
Status Code - HTTP 响应中的状态码
Request - 请求
Response - 响应
Header - HTTP 头,包含元信息
Payload - 请求或响应的实际数据
Rate Limit - 速率限制
Idempotent - 幂等,多次执行结果相同
REST Representational State Transfer 一种 API 架构风格
RPC Remote Procedure Call 远程过程调用
GraphQL - 一种查询语言 API
gRPC - Google 开发的高性能 RPC 框架

原始素材:4-服务器与后端/4.07-api-design.md

前后端如何高效对话? 这就像问:餐厅的菜单怎么设计,客人一看就懂?服务员怎么记单,不会出错?上菜怎么规范,客人满意?API 设计解决的就是"对话规则"的问题。

0. 先问一个问题:你有没有经历过这些噩梦?

场景一:接口命名随心所欲

GET /getUserData
GET /fetchUserInfo
GET /queryUserById
GET /users/query

四个接口,功能一样,命名风格完全不同。新人入职一脸懵:我该用哪个?

场景二:错误处理五花八门


// 有的返回 HTTP 状态码
HTTP/1.1 404 Not Found

// 有的返回 200 + code
HTTP/1.1 200 OK
{ "code": 404, "message": "用户不存在" }

// 有的直接抛异常
HTTP/1.1 200 OK
{ "error": "出错了" }

前端不知道该怎么判断请求是否成功。

场景三:响应结构千人千面


// 接口 A
{ "data": { ... } }

// 接口 B
{ "result": { ... } }

// 接口 C
{ "content": { ... } }

每个接口返回格式都不一样,前端需要针对每个接口单独处理。

好的 API 设计就像餐厅的点餐系统 ——菜单清晰、流程规范、出错有提示。

1. 什么是 API?

API (Application Programming Interface,应用程序编程接口)就是"程序之间对话的约定"。

1.1 用餐厅来类比

餐厅角色 对应概念 说明
菜单 API 文档 告诉你有哪些"菜"可以点
服务员 HTTP 协议 标准化的"对话方式"
后厨 服务端 按"订单"处理请求
上菜 响应 把结果返回给"客人"

1.2 一个完整的 API 请求

API 调用演示:选择端点 GET /api/users | POST /api/users | GET /api/users/999 | POST /api/ordersHTTP Request → 等待中... → HTTP Response

2. API 设计哲学:RPC / REST / GraphQL / gRPC

在开始具体的 RESTful 设计之前,先了解四种主流的 API 设计风格:

REST

最常用

Representational State Transfer,表述性状态转移。由 Roy Fielding 于 2000 年在其博士论文中提出。面向资源,用 URL 标识资源,用 HTTP 方法操作资源。

示例:获取用户信息

GET    /users           # 获取用户列表
GET    /users/123       # 获取单个用户
POST   /users           # 创建用户
PUT    /users/123       # 全量更新
PATCH  /users/123       # 部分更新
DELETE /users/123       # 删除用户

核心特点

✓URL 是名词,不是动词

✓使用 HTTP 方法表达操作

✓无状态,请求包含所有信息

✓可缓存,支持分层系统

适用场景公开 API、CRUD 操作、资源边界清晰的业务

官方地址https://restfulapi.net/

特性 RPC REST GraphQL gRPC
核心理念 面向过程 面向资源 面向数据 面向方法
URL 风格 动词为主 名词为主 单一端点 不依赖URL
学习曲线
性能 一般 一般 较好 优秀
使用占比 ~30% ~50% ~15% ~5%

2.1 REST vs RESTful:有什么区别?

很多人会混淆这两个概念:

概念 含义 说明
REST 一种架构风格 由 Roy Fielding 提出的设计理念,包含一组约束条件
RESTful 符合 REST 风格的 形容词,表示 API 设计遵循了 REST 原则

类比

  • REST 就像"极简主义"——一种设计理念
  • RESTful API 就像"极简风格的房间"——应用了这个理念的具体实现

REST 的六大约束

约束 说明
客户端-服务器分离 前后端独立开发,接口解耦
无状态 每个请求包含所有必要信息,服务器不保存会话状态
可缓存 响应应标明是否可缓存,提高性能
统一接口 使用标准的 HTTP 方法和状态码
分层系统 客户端无需知道连接的是哪层服务器
按需代码 (可选) 服务器可以扩展客户端功能
  1. 学习成本低 :HTTP 协议本身就体现了 REST 思想
  2. 生态成熟 :工具、框架、文档丰富
  3. 通用性强 :任何语言、任何平台都能调用
  4. 易于缓存 :GET 请求天然可缓存,CDN 友好

3. RESTful 设计:让 URL 会说话

REST (Representational State Transfer)是一种架构风格,核心思想是:

  • 把网络上的事物抽象为"资源"(Resource)
  • 用 URL 标识资源
  • 用 HTTP 方法操作资源

3.1 用仓库来类比

仓库概念 REST 对应 示例
货架地址 URL /users/orders
操作方式 HTTP 方法 GET(查看)、POST(入库)
货物 资源 用户数据、订单数据

关键原则 :URL 是名词,不是动词。

3.2 URL 设计规则

规则 错误示例 正确示例 说明
用名词不用动词 /getUsers /users URL 表示资源,HTTP 方法表示操作
用复数形式 /user /users 统一复数风格
小写+连字符 /UserProfiles /user-profiles URL 大小写敏感
避免层级过深 /a/b/c/d/e /a/b/c 最多 3 层
过滤用查询参数 /products/phone/5000 /products?cat=phone 过滤条件用 ? 参数

统一用小写 + 连字符(-)是最安全的做法,避免大小写混乱和下划线风格不一致的问题。

3.3 HTTP 方法选择

方法 用途 幂等性 安全性 典型场景
POST 创建资源 新增用户、提交订单
PUT 全量更新 替换整个用户资料
PATCH 部分更新 只修改昵称
DELETE 删除资源 删除用户、取消订单

幂等性 :多次执行结果相同。

  • 幂等的操作 (GET/PUT/DELETE):点 10 次和点 1 次,结果一样
  • 不幂等的操作 (POST):点 10 次,可能创建 10 个订单

解决方案 :POST 操作用唯一 ID 校验,避免重复处理。

4. 状态码:让错误"会说话"

HTTP 状态码是服务器告诉客户端"发生了什么"的标准方式。

4.1 状态码分类

分类 含义 典型状态码
2xx 成功 200 OK、201 Created、204 No Content
3xx 重定向 301 永久移动、304 未修改
4xx 客户端错误 400 参数错误、401 未认证、404 不存在
5xx 服务端错误 500 内部错误、503 服务不可用

✅ 2xx 成功

状态码 含义 说明
200 OK 请求成功
201 Created 创建成功
204 No Content 成功但无返回内容

⚠️ 4xx 客户端错误

状态码 含义 说明
400 Bad Request 请求格式错误
401 Unauthorized 未认证
403 Forbidden 无权限
404 Not Found 资源不存在
422 Unprocessable 语义错误
429 Too Many 请求过多

❌ 5xx 服务器错误

状态码 含义 说明
500 Server Error 服务器内部错误
502 Bad Gateway 网关错误
503 Unavailable 服务不可用

5. 错误处理:优雅地"拒绝"

好的错误处理能让客户端"看状态码就知道怎么回事",而不是去猜。

4.1 错误处理的"避坑指南"

坑 1:所有错误都返回 200


// ❌ 错误做法
HTTP/1.1 200 OK
{ "error": "出错了" }

问题:缓存层会缓存这个"成功"响应,监控系统发现不了问题。

坑 2:错误信息太笼统


// ❌ 错误做法
HTTP/1.1 400 Bad Request
{ "message": "参数错误" }

问题:客户端不知道哪个参数错了、为什么错。

坑 3:暴露敏感信息


// ❌ 危险做法
HTTP/1.1 500 Internal Server Error
{ "stack": "at UserService.login...", "sql": "SELECT * FROM..." }

危险:暴露了代码结构、数据库查询,攻击者可以利用这些信息。

// 对比好的和差的错误处理方式

❌ 差: 所有错误都 200``❌ 差: 错误信息太笼统``❌ 差: 暴露敏感信息``✅ 好: 正确的状态码``✅ 好: 详细的错误信息``✅ 好: 安全的错误响应

响应结构

6. 版本控制:API 的"向后兼容"

6.1 为什么要版本控制?

场景:你的 App 有 100 万用户,需要修改订单接口。

如果不做版本控制

  • 新 App 调用新接口 → 正常
  • 旧 App 调用新接口 → 字段缺失,崩溃!

正确的做法

  • /v1/orders - 旧接口,继续服务旧 App
  • /v2/orders - 新接口,新功能在这里

6.2 版本控制策略

策略 示例 优点 缺点
URL 路径 /v1/users 直观、易缓存 URL 变长
请求头 Accept: vnd.api.v2+json URL 干净 不便调试
查询参数 /users?version=2 简单 不够标准

6.3 版本演进示例

以用户接口为例,展示 v1 到 v2 的演进:

接口 v1(旧版) v2(新版) 变化说明
获取用户 GET /v1/users
返回:name, email GET /v2/users
返回:name, email, avatar, phone 新增头像、手机号字段
创建订单 POST /v1/orders
接收:items[] POST /v2/orders
接收:items[], coupons[] 新增优惠券支持
批量操作 POST /v2/orders/batch 新增批量创建接口
  • 保持向后兼容 :v1 接口至少维护 6-12 个月,给客户端升级时间
  • 文档同步更新 :每个版本有独立的 API 文档
  • 废弃公告 :提前通知 v1 将在何时下线,引导迁移
  • 监控使用情况 :统计 v1 调用量,确认可以安全下线后再停止服务

7. 响应结构设计

响应结构是前后端协作的"数据契约",统一格式能大幅降低沟通成本。

❓ 为什么统一📝 字段说明🔢 状态码📄 示例📑 分页

为什么要统一响应格式?

❌ 问题:不同接口返回格式不一致

// 接口 A
{ "data": { "user": {...} } }

// 接口 B
{ "result": { "user": {...} } }

// 接口 C
{ "user": {...} }

前端需要针对每个接口单独处理,代码冗余,容易出错

✅ 解决:统一响应格式

{
  "code": 0,
  "message": "success",
  "data": { ... },
  "request_id": "req-xxx"
}

7.1 大厂实践参考

Google API 设计指南

参考 Google API Design Guide,Google 要求所有 API 错误响应必须包含 google.rpc.Status 消息结构:


{
  "error": {
    "code": 429,
    "message": "资源不足,请稍后重试",
    "status": "RESOURCE_EXHAUSTED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "RESOURCE_AVAILABILITY",
        "domain": "compute.googleapis.com",
        "metadata": {
          "zone": "us-east1-a",
          "service": "compute"
        }
      }
    ]
  }
}

核心要求

  • 必须包含 ErrorInfo 提供机器可读的错误标识
  • message 面向开发者,用简洁语言描述问题和解决方案
  • details 数组可包含 LocalizedMessage(本地化消息)、Help(帮助链接)等

Microsoft REST API 指南

参考 Microsoft REST API Guidelines,微软强调响应的一致性:

错误与故障的分类

  • 错误(Error) :客户端传递无效数据导致,返回 4xx,不影响 API 可用性
  • 故障(Fault) :服务端无法正确响应有效请求,返回 5xx,影响 API 可用性

响应标头规范

  • Date:必须返回,使用 RFC 5322 格式(GMT 时区)
  • Content-Type:必须返回
  • ETag:支持乐观并发控制的资源必须返回

阿里巴巴 Java 开发手册

参考 阿里巴巴 Java 开发手册,阿里对 API 响应有以下规范:

统一返回对象


public class Result<T> {
    private Integer code;
    private String message;
    private T data;
    private String requestId;
}

错误码分段设计

范围 类型 示例
0 成功 0
1xxxx 参数错误 10001 缺少必填参数
2xxxx 业务错误 20001 余额不足
3xxxx 认证错误 30001 未登录
5xxxx 系统错误 50001 数据库异常
Stripe API 响应设计

参考 Stripe API Documentation,Stripe 的错误响应设计非常精细:


{
  "error": {
    "type": "card_error",
    "code": "card_declined",
    "message": "Your card was declined.",
    "param": "number",
    "decline_code": "insufficient_funds",
    "doc_url": "https://stripe.com/docs/error-codes/card-declined"
  }
}

设计亮点

  • type 区分错误类型:api_errorcard_errorinvalid_request_error
  • param 指出具体哪个参数出错,前端可直接定位表单字段
  • doc_url 提供文档链接,开发者可深入了解
  • decline_code 提供更细粒度的错误原因

JSON:API 规范

参考 JSON:API Specification,这是一个业界广泛采纳的 JSON API 响应规范:


{
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API 规范详解"
    },
    "relationships": {
      "author": {
        "data": { "type": "users", "id": "9" }
      }
    }
  },
  "included": [
    {
      "type": "users",
      "id": "9",
      "attributes": {
        "name": "张三"
      }
    }
  ]
}

核心设计

  • data 包含主资源,必须有 typeid
  • attributes 存放资源属性
  • relationships 描述资源关联
  • included 避免重复请求,一次性返回关联数据

GitHub REST API 响应设计

参考 GitHub REST API Documentation,GitHub 的响应设计注重开发者体验:

成功响应


{
  "id": 1296269,
  "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
  "name": "Hello-World",
  "full_name": "octocat/Hello-World",
  "owner": {
    "login": "octocat",
    "id": 1,
    "avatar_url": "https://github.com/images/error/octocat_happy.gif"
  },
  "private": false,
  "html_url": "https://github.com/octocat/Hello-World"
}

错误响应


{
  "message": "Bad credentials",
  "documentation_url": "https://docs.github.com/rest"
}

设计亮点

  • 响应包含多种 URL 格式(html_urlurl)方便不同场景使用
  • 错误响应包含 documentation_url 指向文档
  • 使用 Link 响应头实现分页导航

Twitter/X API v2 响应设计

参考 Twitter API v2 Documentation,Twitter API v2 采用简洁的响应格式:


{
  "data": {
    "id": "1460323737035677698",
    "text": "Hello, Twitter!"
  },
  "includes": {
    "users": [
      {
        "id": "2244994945",
        "name": "Twitter Dev",
        "username": "TwitterDev"
      }
    ]
  }
}

设计亮点

  • data 包含主数据,includes 包含关联数据(类似 JSON:API)
  • 支持字段选择:?tweet.fields=created_at,public_metrics
  • 分页使用 next_tokenprevious_token

7.2 最佳实践总结

综合以上规范,响应结构设计应遵循以下原则:

  1. 一致性优先 :所有接口使用相同的响应结构,前端可统一封装请求层
  2. 机器可读 :错误码 + 错误原因(reason)让程序能自动处理
  3. 人类友好 :message 描述清晰,包含解决建议
  4. 可追踪 :request_id 贯穿请求全链路,便于问题定位
  5. 国际化支持 :通过 details 扩展本地化消息

7.3 data 字段设计规范

data 是响应的核心,其设计直接影响前端开发效率。

单对象 vs 列表

单对象

{
  "code": 0,
  "data": {
    "id": 123,
    "name": "张三"
  }
}

列表

{
  "code": 0,
  "data": {
    "items": [...],
    "pagination": {
      "page": 1,
      "total": 100
    }
  }
}

列表数据包裹在 items 数组中,分页信息放在 pagination 对象

7.4 错误响应设计进阶

⚠️错误响应设计进阶

参数校验错误

{
  "code": 10001,
  "message": "参数校验失败",
  "data": {
    "errors": [
      {
        "field": "email",
        "message": "邮箱格式不正确",
        "value": "invalid-email"
      },
      {
        "field": "password",
        "message": "密码长度至少 8 位",
        "value": "123"
      }
    ]
  }
}

field出错字段名,前端可定位表单

message用户友好的错误描述

value客户端提交的值(可选)

参考链接

8. 实战:电商系统 API 设计示例

# 用户模块
GET    /v1/users                    # 获取用户列表
POST   /v1/users                    # 创建新用户
GET    /v1/users/{id}               # 获取用户详情
PUT    /v1/users/{id}               # 全量更新用户
PATCH  /v1/users/{id}               # 部分更新用户
DELETE /v1/users/{id}               # 删除用户

# 订单模块
GET    /v1/users/{id}/orders        # 获取某用户的订单
POST   /v1/orders                   # 创建订单
GET    /v1/orders/{id}              # 获取订单详情
PATCH  /v1/orders/{id}/status       # 更新订单状态

# 商品模块(复杂过滤用查询参数)
GET    /v1/products?category=phone&price_max=5000&sort=price_desc&page=1

9. 用 AI 辅助设计 API

AI 可以帮助你快速生成符合规范的 API 设计。关键在于提供清晰的上下文和约束条件。

9.1 提示词模板

你是一位资深的后端架构师,精通 RESTful API 设计。请帮我设计一套 API 接口。

## 业务背景
[描述你的业务场景,例如:电商系统、博客平台、任务管理等]

## 功能需求
[列出需要的功能模块,例如:
- 用户管理:注册、登录、个人信息
- 订单管理:创建订单、查询订单、取消订单
- 商品管理:商品列表、商品详情、搜索]

## 设计要求
1. 遵循 RESTful 规范
2. URL 使用名词复数,小写+连字符
3. 正确使用 HTTP 方法(GET/POST/PUT/PATCH/DELETE)
4. 统一的响应格式:{ code, message, data, request_id }
5. 合理的状态码使用
6. 版本控制:URL 路径方式(/v1/)

## 输出格式
请按以下格式输出:

### 接口列表
| 方法 | URL | 描述 | 请求体 | 响应体 |
|------|-----|------|--------|--------|

### 请求/响应示例
[关键接口的详细示例]

### 状态码说明
[使用的状态码及其含义]

9.2 实战示例:电商订单 API

输入提示词:

 你是一位资深的后端架构师,精通 RESTful API 设计。请帮我设计一套电商订单系统的 API 接口。

## 业务背景
一个 B2C 电商平台,用户可以浏览商品、下单购买、查看订单状态。

## 功能需求
- 订单模块:创建订单、查询订单列表、查询订单详情、取消订单、支付订单
- 购物车模块:添加商品、修改数量、删除商品、查看购物车

## 设计要求
1. 遵循 RESTful 规范
2. URL 使用名词复数,小写+连字符
3. 正确使用 HTTP 方法
4. 统一的响应格式
5. 版本控制:/v1/

AI 输出示例:

方法 URL 描述
POST /v1/orders 创建订单
GET /v1/orders 查询订单列表
GET /v1/orders/{id} 查询订单详情
PATCH /v1/orders/{id}/status 更新订单状态(取消/支付)
GET /v1/users/{id}/cart 获取购物车
POST /v1/users/{id}/cart/items 添加商品到购物车
PATCH /v1/users/{id}/cart/items/{itemId} 修改购物车商品数量
DELETE /v1/users/{id}/cart/items/{itemId} 删除购物车商品

9.3 AI 辅助设计的注意事项

注意点 说明
提供完整上下文 业务背景、用户角色、数据关系都要说清楚
明确约束条件 命名规范、版本策略、响应格式等要提前定义
迭代优化 第一次输出可能不完美,追问细节、要求修改
人工审核 AI 生成的内容需要人工检查是否符合业务需求
补充边界情况 让 AI 考虑错误处理、权限控制、分页等边界情况
  • "请补充每个接口的错误响应示例"
  • "请考虑分页、排序、过滤参数"
  • "请添加接口的权限控制说明"
  • "请检查是否符合 RESTful 最佳实践"

名词速查表

名词 英文 解释
API Application Programming Interface 程序之间对话的约定
REST Representational State Transfer 一种架构风格,用 URL 标识资源
资源 Resource REST 架构的核心概念,有唯一标识(URL)
幂等性 Idempotency 多次执行结果相同
状态码 Status Code HTTP 协议定义的响应状态
版本控制 Versioning 让新旧 API 并存,平滑升级
请求体 Request Body POST/PUT/PATCH 请求携带的数据
响应体 Response Body 服务器返回的数据
Header Header 请求/响应的元数据(如 Content-Type)
认证 Authentication 验证"你是谁"(登录、Token)
授权 Authorization 验证"你能做什么"(权限)