JSON、表单与图片接口的响应设计:错误信封统一,成功载荷分开
三类接口应共用一个外层:HTTP 状态码分层、统一的错误信封(机器码、可读信息、追踪标识、字段级明细),成功载荷则按媒体类型分开——JSON 返回可演进的对象,表单接口把校验错误映射回字段路径,图片接口返回二进制流并在头部声明类型、长度与缓存元数据。错误一律用非 2xx 加 JSON 错误体,客户端按 Content-Type 分流。API.PLUS 具体端点的实际行为本次无材料,待核实。
- 错误响应统一成 JSON 错误信封,图片接口失败时也返回它,不要返回一张错误图片。
- 成功响应按媒体类型分流:JSON 返回结构化对象,表单接口仍返回 JSON 但带上字段级明细,图片返回二进制流加头部元数
- 不要让 200 携带业务错误码,否则缓存、监控与重试策略失去判断依据。
三类接口最容易出错的地方,在于是否把「结果状态」和「成功载荷」放在同一层;字段命名反而是次要的。可行的做法是:所有接口共用一个错误信封;成功载荷按媒体类型分开——JSON 接口返回结构化对象,表单接口返回字段级校验结果(仍是 JSON),图片接口返回二进制流并在头部声明元数据。下面是设计建议,不是 API.PLUS 的具体接口行为;该平台各端点的实际实现本次无材料,待核实。
一、共同外层:状态码分层,错误信封承载细节#
HTTP 状态码承担第一层分类:2xx 表示成功,4xx 表示调用方需要修改请求,5xx 表示服务端问题。信封只负责细节,常见字段如下(字段名可替换,语义要对齐):
code:机器可读的稳定标识,不随文案调整而变;message:面向人的说明,可本地化;trace_id:贯穿日志的关联标识,便于报障时对齐;details:字段路径到具体问题的映射,供表单类场景直接标注。
把业务错误塞进
200 OK的errno字段,会让缓存、监控告警和自动重试都失去判断依据。这是设计上的取舍建议,不是对任何现有接口的描述。
另外,错误响应也要声明 Content-Type: application/json,否则客户端无法区分「服务端真的返回了 JSON」和「中间层插入的 HTML 错误页」。
二、JSON:成功体保持可演进#
- 顶层用对象而非数组,后续加字段不会破坏解析逻辑;列表放进对象字段中。
- 「字段缺失」与「字段为 null」含义不同,需在使用文档中写明,不要混用。
- 时间统一为带时区的字符串格式,避免同一字段出现多种精度。
下面是未执行的示例,仅示意结构,非真实端点:
POST https://api.example.com/v1/orders
Authorization: Bearer YOUR_KEY
Content-Type: application/json
{ "items": [] }
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{ "code": "VALIDATION_FAILED",
"message": "请求体校验未通过",
"trace_id": "demo-trace",
"details": [ { "field": "items", "issue": "must not be empty" } ] }
三、表单:把校验错误映射回字段#
表单请求通常以 application/x-www-form-urlencoded 或 multipart/form-data 编码,但响应仍建议用 JSON,便于客户端拿到结构化的字段级错误。两点边界值得先定:
- 不要用 302 重定向表达校验失败。浏览器会跟随跳转,API 客户端通常不会,同一接口的行为因调用方不同而分叉。
details里的字段路径要和表单字段名一致,前端才能直接把提示挂到对应输入框。
四、图片与二进制:成功走流,失败走 JSON#
- 成功响应声明
Content-Type(如image/png)、Content-Length,按需补充ETag与Cache-Control。 - 失败响应返回非 2xx 状态码加 JSON 错误信封,不要用一张错误占位图充当错误,否则客户端无法区分「图片就是这样」和「请求失败了」。
- 客户端按响应的
Content-Type分流解析,不依赖 URL 后缀或请求时的预期。 - 默认不要把图片 base64 内联进 JSON,二者在体积、流式读取和缓存上的处理方式不同;是否需要内联,取决于具体客户端约束,待核实。
| 载荷类型 | 成功响应 | 错误响应 |
|---|---|---|
| JSON | 对象 + 结构化字段 | 非 2xx + JSON 错误信封 |
| 表单 | JSON,含字段级结果 | 非 2xx + details 字段路径 |
| 图片 | 二进制流 + 头部元数据 | 非 2xx + JSON 错误信封 |
五、落地顺序#
- 先写一份响应契约文档,固定状态码分层与错误信封字段;
- 再定错误码表,
code一旦发布就不要复用为其他含义; - 客户端统一写一个分流层:先看状态码,再看
Content-Type; - 接入具体平台时,用自己的密钥在其测试环境完整记录一次请求与响应,作为契约基线。
尚不能确认的部分#
API.PLUS 各接口是否采用统一错误码、是否支持 Accept 内容协商、图片接口是否支持 Range 与条件请求,本次均无材料支撑,待核实;接入前请以其官方文档与测试环境返回为准。本文涉及的标准条款与具体规范编号,本次未核对原文,不做引用。