用户登录

技术文章

外部链接将在新标签页打开。

JSON、表单与图片接口的响应契约:状态码、Content-Type 与错误体怎么分工

一句话回答

三类接口不必共用同一个响应体,但应共用同一套判断顺序:先由状态码判定成功或失败,再由 Content-Type 决定解析方式,最后才读取响应体字段。文章给出的具体建议包括:JSON 成功体要保持全局一致;错误体至少包含稳定的机器码、面向人的描述和请求标识;图片接口用具体 image 类型加响应头表达元数据与缓存,出错时返回 JSON 错误体而不是占位图;表单提交用 303 重定向或直接返回 JSON 都可行,但校验失败要用 4xx 表达;兼容性上优先加字段、用媒体类型承载版本。

先给结论:JSON、表单、图片这三类接口不必共用同一个响应体,但应共用同一套判断顺序——先看状态码判断成功还是失败,再看 Content-Type 决定怎么解析,最后才在响应体里找字段。这套顺序在整站保持一致,客户端就不必为每个端点写特殊分支。本文讨论的是响应契约的设计取舍,不含任何厂商实测;涉及具体平台的行为,需以其官方文档为准,本文未做核验。

一、先把判断顺序固定下来#

常见的客户端写法是先 JSON.parse 再判断业务码。一旦响应体是图片流、空体或 HTML 错误页,解析阶段就会先抛错,真正的状态信息反而丢失。把顺序倒过来可以避免这种耦合。

  • 2xx:成功。响应体结构由 Content-Type 声明,客户端按类型分发。
  • 3xx:需要跟随跳转或改变请求方式,表单提交后最常见。
  • 4xx:请求侧问题,原样重试通常没有意义;408、429 是例外,且应参考 Retry-After。
  • 5xx:服务端问题,能否重试取决于该请求是否幂等,不能只看状态码。

二、JSON 成功响应:信封还是裸对象#

两种都可以,关键是全局一致,不要同一套 API 里一半裸对象一半信封。

方案优点代价
裸对象 {"id": ...}直观,便于类型生成与缓存没有固定位置放业务失败信息
信封 {"data": ..., "request_id": ...}结构稳定,易追加元信息多一层解包

若选信封,注意不要让 HTTP 状态码和 body 里的 code 表达互相矛盾的结果:例如鉴权失败返回 200 再在 body 里写“未登录”,会让网关、缓存和监控全部失效。body 里的业务码只应细分 HTTP 已表达的结果。

三、错误体:最少三件事#

一个可用的错误体需要:稳定的机器可读码、面向人的描述、可用于排障的请求标识。

{
  "error": {
    "code": "invalid_image_format",
    "message": "仅接受 image/png、image/jpeg",
    "field": "file"
  },
  "request_id": "req_demo_0001"
}

上例为未执行的演示,域名、标识均为占位。三条约束:code 是契约,不能随文案调整而变更;message 面向人,可本地化;request_id 要能贯穿服务端日志。错误体里不要出现堆栈、SQL 语句或内部主机名。

四、图片接口:二进制与元数据分开#

返回图片时,Content-Type 应是具体的 image/png、image/jpeg,而不是让客户端去嗅探的通用类型;可缓存性用 ETag、Cache-Control、Content-Length 表达。

  • 元数据:宽高、格式等信息放响应头,或提供 Accept: application/json 的元数据变体。同一 URL 有两种表示时,应带 Vary: Accept,否则缓存可能串味。
  • 失败:不要返回 200 加一张占位图。应返回 4xx/5xx 加 JSON 错误体,客户端按 Content-Type 分流。
  • 下载语义:用 Content-Disposition: attachment; filename="...",文件名需转义。

图片地址是否带签名、有效期多长,属各供应商策略,请查对应文档,本文不给数值。

五、表单提交:重定向还是 JSON#

传统 HTML 表单在 POST 后返回 303 重定向到结果页,可以避免刷新造成重复提交;前后端分离场景下,无论请求体是 application/x-www-form-urlencoded 还是 multipart/form-data,通常直接返回 application/json。两种都合理,取决于由谁渲染结果。

校验失败建议用 400 或 422,把字段级错误放进响应体,不要用 200 加 {"success": false} 掩盖。multipart 上传还要说明体积上限与超限时的返回(通常是 413),具体阈值以服务端配置为准,本文不作断言。

六、变更时的兼容边界#

  • 新增字段一般向后兼容;删除字段、改类型、改语义不兼容。版本可用路径前缀或媒体类型(如 application/vnd.example.v2+json)承载。
  • 新增状态码前,先确认客户端对未知 4xx 有安全的默认分支。
  • 时间统一用 ISO 8601 并带时区;ID 用字符串返回,避免前端大整数精度问题。

适用范围说明#

以上为通用设计建议,不含性能数据与实测记录,代码片段为未执行的演示。API.PLUS 各端点的实际字段、错误码与限流策略,请以其官方文档为准。

作者:沐小悠

本文约 6 分钟读完 · 关键词:响应设计、Content-Type、HTTP 状态码、错误响应格式、图片接口

更多文章 GET 示例接口

「」标签下的其他文章