📋
← 返回教程列表

在 REST API 中使用 JSON:最佳实践

· 标签: json, rest-api, api-design, json-best-practices, pagination, web-development

REST API 中的 JSON

JSON 和 REST API 是天作之合。JSON 轻量级的语法、原生的数组支持以及普遍的语言支持,使其成为现代 Web API 的默认格式。但仅仅在 API 中使用 JSON 是不够的 -- 遵循既定的约定和最佳实践,才能确保你的 API 一致、直观且易于集成。

请求和响应格式

一致的封装结构

为所有 API 响应采用一致的 JSON 封装。这使客户端处理具有可预测性,并简化错误处理。

{
  "status": "success",
  "data": {
    "user": {
      "id": 123,
      "name": "Alice",
      "email": "alice@example.com"
    }
  },
  "meta": {
    "requestId": "req-a1b2c3d4",
    "timestamp": "2026-07-19T10:30:00Z"
  }
}

Snake Case 与 Camel Case

选择一种命名约定,并在整个 API 中始终坚持使用:

  • Camel CasecreatedAtfirstName):常见于 JavaScript/TypeScript 生态系统
  • Snake Casecreated_atfirst_name):常见于 Python、Ruby 和 PHP 生态系统

无论你选择哪种,都要清楚地记录下来;如果你的后端语言使用不同的约定,可以考虑使用一层转换层。

HTTP 状态码与 JSON

恰当的 HTTP 状态码能补充你的 JSON 响应。请一致地使用它们:

| 状态码 | 含义 | 使用场景 | |-------------|---------|-------------| | 200 OK | 成功 | GET、PUT、PATCH 成功 | | 201 Created | 资源已创建 | POST 成功 | | 204 No Content | 删除成功 | DELETE 成功(无 JSON 响应体) | | 400 Bad Request | JSON 语法无效 | 请求体格式错误 | | 401 Unauthorized | 需要身份验证 | 令牌缺失或无效 | | 403 Forbidden | 权限不足 | 身份验证有效但不被允许 | | 404 Not Found | 资源不存在 | ID 或路径无效 | | 422 Unprocessable Entity | 校验失败 | 有效 JSON 中的语义错误 | | 429 Too Many Requests | 触发速率限制 | 客户端超出限制 | | 500 Internal Server Error | 服务器端故障 | 意外错误 |

标准错误响应格式

{
  "status": "error",
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The request body contains invalid fields",
    "details": [
      {
        "field": "email",
        "message": "Must be a valid email address",
        "code": "INVALID_FORMAT"
      },
      {
        "field": "age",
        "message": "Must be a positive integer",
        "code": "OUT_OF_RANGE"
      }
    ]
  }
}

嵌套资源

表示关系

REST API 经常需要表示相关资源。以下是常见模式:

嵌入式(eager loading):

{
  "order": {
    "id": 5001,
    "total": 29.99,
    "customer": {
      "id": 123,
      "name": "Alice",
      "email": "alice@example.com"
    },
    "items": [
      {
        "productId": 42,
        "name": "Widget",
        "quantity": 2,
        "price": 14.99
      }
    ]
  }
}

引用式(lazy loading)-- 使用 ID 并提供单独的端点:

{
  "order": {
    "id": 5001,
    "total": 29.99,
    "customerId": 123,
    "itemIds": [101, 102]
  }
}

经验法则: 嵌入总是需要一起获取的相关数据。对按条件或在不同时间获取的数据使用引用。

分页模式

在返回资源列表时,分页必不可少。请使用一致的分页格式:

基于偏移量的分页

{
  "status": "success",
  "data": [
    { "id": 1, "name": "User 1" },
    { "id": 2, "name": "User 2" }
  ],
  "pagination": {
    "page": 1,
    "perPage": 20,
    "totalItems": 156,
    "totalPages": 8,
    "links": {
      "first": "/api/users?page=1&perPage=20",
      "prev": null,
      "next": "/api/users?page=2&perPage=20",
      "last": "/api/users?page=8&perPage=20"
    }
  }
}

基于游标的分页(推荐用于大数据集)

{
  "status": "success",
  "data": [
    { "id": 100, "name": "User 100" },
    { "id": 101, "name": "User 101" }
  ],
  "pagination": {
    "nextCursor": "eyJpZCI6MTAxfQ==",
    "hasMore": true
  }
}

对于新记录可能改变页面边界的实时数据,基于游标的分页更可靠。

API 请求中的 JSON

POST / PUT 请求体

使用 Content-Type: application/json 请求头接受 JSON:

{
  "title": "New Blog Post",
  "content": "This is the content...",
  "tags": ["json", "rest-api"],
  "published": false
}

使用 PATCH 进行部分更新

使用 PATCH 进行部分更新。只接受应该变更的字段:

// PATCH /api/users/123
{
  "email": "newemail@example.com"
}

过滤、排序和搜索

使用查询参数进行数据操作,保持 JSON 请求体干净整洁:

GET /api/users?filter[role]=admin&sort=-createdAt&search=alice
{
  "status": "success",
  "data": [ /* filtered, sorted results */ ]
}

速率限制

在响应头中包含速率限制信息,也可以选择性地包含在 JSON 响应体中:

{
  "status": "error",
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Please try again later."
  },
  "meta": {
    "rateLimit": {
      "limit": 100,
      "remaining": 0,
      "resetAt": "2026-07-19T11:00:00Z"
    }
  }
}

JSON 最佳实践清单

  • [ ] 使用一致的键命名(全程使用 camelCase 或 snake_case)
  • [ ] 每次响应都返回恰当的 HTTP 状态码
  • [ ] 包含一致的错误格式,并带有机器可读的错误码
  • [ ] 使用标准化的分页对象对列表端点进行分页
  • [ ] 使用 JSON Schema 记录并校验请求/响应结构
  • [ ] 在所有 JSON 端点设置 Content-Type: application/json
  • [ ] 在生产环境中使用 gzip 或 brotli 压缩 JSON 响应
  • [ ] 强制执行最大负载大小限制(例如默认为 1MB)
  • [ ] 使用 HTTPS 加密传输中的 JSON 数据
  • [ ] 结构化错误详情,帮助客户端调试而不暴露内部信息

校验你的 API JSON

在 API 响应到达客户端之前,先用 JSON 校验器校验一遍,以便尽早发现格式化错误。一致且有效的 JSON 响应能让你的 API 可靠且对开发者友好。在开发过程中,可以使用我们的 JSON Formatter & Validator 工具来测试你的数据负载。