跳转到内容

Api请求响应体规范

统一返回结构、字段命名、时间格式、空值处理


[Requirement] 请求体必须使用 application/json(Content-Type: application/json; charset=utf-8),禁止混用 x-www-form-urlencoded 与 JSON。

[Standard] 文件上传使用 multipart/form-data,且每个上传字段需在文档中标注文件类型与大小限制。

[Requirement] 所有入参必须做类型、范围、必填校验,校验失败返回 400 并指明具体字段。

[Standard] 入参对象与出参对象分离定义(XxxCreateRequest / XxxUpdateRequest / XxxResponse),不复用数据库实体。

# 入参 DTO
class UserCreateRequest(BaseModel):
    name: str = Field(..., min_length=1, max_length=50)
    email: EmailStr
    age: int | None = Field(None, ge=0, le=150)
 
# 出参 DTO
class UserResponse(BaseModel):
    id: int
    name: str
    email: str
    created_at: datetime

[Default] 单请求体默认上限 1 MB;超过需使用分块上传或专门的大文件接口,并在网关层拦截超限请求返回 413 Payload Too Large。


[Requirement] 所有业务响应必须使用统一信封结构,包含 code、message、data、trace_id 四个字段。

{
  "code": 0,
  "message": "ok",
  "data": { ... },
  "trace_id": "7f3a9c2e1b4d..."
}
字段类型说明
codeint业务码,0 表示成功,非 0 表示业务错误(见错误码规范)
messagestring面向调用方的可读消息,成功为 ok
dataobject/array/null业务数据,无数据时为 null
trace_idstring全链路追踪 ID,便于排查

[Caution] HTTP 状态码与 code 字段不可互相替代:HTTP 状态码表达传输层结果,code 表达业务层结果。成功时 HTTP 200 + code: 0;业务错误时 HTTP 4xx + 对应 code。

[Standard] 列表接口的 data 为对象,包含 items 与 pagination,禁止直接返回数组。

{
  "code": 0,
  "message": "ok",
  "data": {
    "items": [ ... ],
    "pagination": { "page": 1, "page_size": 20, "total": 156, "total_pages": 8 }
  },
  "trace_id": "..."
}

[Caution] 禁止在成功响应中混入 error、success、result 等多余字段,保持结构统一。

// 反模式:字段不统一
{ "status": "success", "result": {...}, "msg": "done" }
{ "success": true, "data": {...}, "error": null }

[Requirement] JSON 字段使用 snake_case(下划线小写),与 Python/Go 后端语言风格一致。

[Standard] 布尔字段以 is_ / has_ / can_ 开头,如 is_active、has_avatar、can_edit。

[Standard] ID 字段以资源名 + _id 结尾,如 user_id、order_id;资源自身主键使用 id。

场景字段名
创建/更新时间created_at、updated_at
时间范围created_from、created_to
数量total_count、page_size
金额amount、total_amount(单位见下)
枚举status、type、level

[Requirement] 金额字段以分为单位(整数),避免浮点数精度问题;在文档中明确单位。

{ "amount": 1299 }   // 表示 ¥12.99

[Caution] 禁止使用 float 传输金额,禁止在前端用 toFixed 后再传字符串替代整数。


[Requirement] 所有时间字段使用 ISO 8601 格式,带时区,统一为 UTC:2026-10-14T08:30:00Z。

[Standard] 时间戳字段名以 _at 结尾;纯日期使用 _date 结尾,格式 YYYY-MM-DD。

[Default] 内部存储使用 datetime(带时区),仅在序列化层转为 ISO 字符串,禁止在业务逻辑中传字符串时间。

字段类型格式示例
时间戳ISO 8601 UTC2026-10-14T08:30:00Z
日期YYYY-MM-DD2026-10-14
时长ISO 8601 DurationPT1H30M(1.5 小时)

[Caution] 后端一律以 UTC 存储与传输,前端负责按用户时区展示;禁止后端返回带本地时区偏移的时间(如 +08:00)。

// 反模式
{ "createTime": "2026/10/14 16:30" }      // 非 ISO、用斜杠、无时区
{ "created_at": 1728894600 }               // 时间戳数字(易混淆秒/毫秒)
{ "created_at": "2026-10-14T16:30:00+08:00" } // 带本地偏移,应统一为 UTC

[Requirement] 字段值不存在时返回 null,禁止返回空字符串 "" 或 0 来表示”无”。

[Standard] 区分”字段不存在”与”字段值为 null”:响应中声明过的字段必须出现(值可为 null),未声明字段不出现。

// 正确:无头像时返回 null
{ "id": 1, "name": "张三", "avatar_url": null }
 
// 错误
{ "id": 1, "name": "张三", "avatar_url": "" }   // 用空串表示无
{ "id": 1, "name": "张三" }                      // 字段缺失

[Standard] 列表字段为空时返回 [],不返回 null,以便调用方直接遍历。

{ "tags": [], "roles": [] }

[Default] PATCH 请求中,未传字段表示”不修改”,传 null 表示”置空”;二者语义必须区分。

PATCH /api/v1/users/123
{ "nickname": null }   // 将 nickname 置空
// 不传 nickname       // 不修改 nickname
// 反模式
{ "phone": "" }          // 无手机号应返回 null
{ "tags": null }         // 空集合应返回 []
{ "deleted_at": 0 }      // 未删除应返回 null