Skip to content

API 设计与接口规范 ​

这篇用于沉淀接口设计时真正会反复复用的通用规范。重点不是背标准原文,而是把日常做接口时最容易反复讨论的点收口成一套可执行规则。

一、先定设计原则 ​

接口设计最怕两种情况:

  1. 只顾着把功能做出来,没有统一风格,最后每个接口都像不同人写的。
  2. 过度追求“完美规范”,结果文档和实现完全脱节。

实际落地时,更适合抓住下面 5 条:

  1. 资源优先:先想清楚系统里有哪些资源,再定义接口,而不是先写一堆动作型 URL。
  2. HTTP 语义清晰:GET 查、POST 建、PUT/PATCH 改、DELETE 删,避免“全站一个 POST”。
  3. 返回结构稳定:前端和调用方最怕字段风格、错误格式、分页结构来回变。
  4. 文档和实现同源:能从代码或配置生成文档,就不要维护两套真相。
  5. 先统一最常用的 80%:命名、状态码、鉴权、分页、错误响应优先统一,细节扩展后补。

二、URL 设计的基本规则 ​

1. 按资源建模 ​

推荐:

  • /users
  • /orders
  • /orders/{id}
  • /orders/{id}/items

不推荐:

  • /getUserList
  • /saveOrder
  • /deleteOrderById

原因很简单:资源化 URL 更稳定,也更容易配合文档、权限、版本控制和 SDK 生成。

2. 名称统一 ​

  • 路径尽量用小写英文和 kebab-case
  • 集合用复数更自然,比如 users、orders
  • 避免中英混用、拼音缩写、项目内部黑话

3. 查询参数只做“筛选/排序/分页” ​

例如:

text
GET /orders?status=paid&page=1&pageSize=20&sort=createdAt:desc

不要把“修改状态”“确认收货”这类动作塞进查询参数。

三、HTTP 方法怎么用 ​

方法用途常见场景
GET查询资源列表、详情
POST创建资源 / 执行动作新增、导入、发起任务
PUT整体更新用完整对象覆盖
PATCH部分更新更新状态、改单个字段
DELETE删除资源逻辑删除 / 物理删除

实践建议:

  • 如果只是查数据,不要用 POST
  • 如果是“执行动作”,要明确它不是普通 CRUD,例如 /orders/{id}:cancel
  • 如果团队还不习惯 PATCH,可以统一退回 PUT + 明确字段约束,但不要同一系统混着乱用

四、请求与响应建议 ​

1. 请求体 ​

  • 字段命名统一一种风格,推荐 camelCase
  • 时间字段统一格式,优先 ISO 8601
  • 金额、数量、状态等关键字段类型要稳定,不要今天是字符串,明天是数字

2. 响应体 ​

如果是面向业务系统的内部接口,建议保持统一响应信封,例如:

json
{
  "success": true,
  "code": "OK",
  "message": "",
  "data": {
    "id": 1001,
    "name": "demo"
  }
}

如果是更偏开放平台或标准化接口,可以尽量贴近 JSON:API / OpenAPI 这类规范,但前提是团队真的能持续遵守。

3. 分页结构 ​

分页尽量固定,不要每个接口自己定义一套:

json
{
  "success": true,
  "data": {
    "items": [],
    "page": 1,
    "pageSize": 20,
    "total": 135
  }
}

五、状态码与错误响应 ​

状态码不用追求花样多,先把最常用的定义稳定:

状态码含义说明
200成功查询、更新成功
201创建成功新增资源
400请求参数错误字段缺失、格式错误
401未认证Token 缺失或失效
403无权限已登录但无权访问
404资源不存在ID 无效或已删除
409冲突唯一键冲突、状态冲突
500服务端异常未处理异常

错误响应建议至少统一这几项:

json
{
  "success": false,
  "code": "ORDER_STATUS_INVALID",
  "message": "当前订单状态不允许取消",
  "details": null
}

重点:

  • message 给人看
  • code 给程序判断
  • 不要把数据库报错、堆栈信息直接透出到外部接口

六、版本控制怎么做 ​

接口版本控制通常只在这几种情况值得上:

  1. 对外开放接口,调用方多,兼容性要求高
  2. 同一资源模型要长期演进
  3. 老客户端无法同步升级

常见做法:

  • URL 版本:/api/v1/orders
  • Header 版本:Accept: application/vnd.company.v1+json

如果只是内部系统、调用方可控,没必要一开始就做复杂版本治理。 更实际的策略是:先把字段设计稳住,再决定是否需要显式版本号。

七、文档化建议 ​

接口文档至少要解决 4 个问题:

  1. 这个接口是干什么的
  2. 需要哪些参数
  3. 返回什么结构
  4. 错误时会给什么响应

在 .NET / Java 项目里,推荐优先用 OpenAPI 体系生成文档,再人工补充说明。 这样能保证“文档和代码尽量同源”,比单独维护 Word/Markdown 接口表可靠得多。

八、用 curl 做最小验证 ​

接口设计完之后,最好先用 curl 做最小可用验证。 原因很简单:curl 不依赖图形界面,最容易暴露请求方法、Header、参数和返回体是否真的设计合理。

例如:

bash
curl -X GET "https://api.example.com/orders/1001" \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json"

如果一个接口连 curl 都很难说明白,通常意味着接口设计还不够清晰。

九、什么时候参考 JSON:API / OpenAPI ​

JSON:API 适合看什么 ​

  • 资源关系怎么表达
  • 响应结构如何保持一致
  • 包含关联资源时怎么展开

OpenAPI 适合看什么 ​

  • 如何描述接口契约
  • 如何生成文档
  • 如何给前后端、测试、SDK 提供统一接口定义

简单理解:

  • JSON:API 更偏响应风格和资源表达
  • OpenAPI 更偏接口描述和文档契约

十、自己以后复用时最该统一的清单 ​

以后写新接口,优先先对齐下面这份清单:

  • URL 命名规则
  • 请求方法使用规则
  • 分页结构
  • 错误响应格式
  • 状态码使用范围
  • 鉴权方式
  • 时间与金额字段格式
  • OpenAPI 文档生成方式

只要这 8 项统一,接口系统的可维护性就会明显提升。

参考资料 ​

方舟 · Ark