3. Problem Details JSON 对象
问题详情 (problem details) 的规范模型是一个 JSON [RFC7159] 对象.
当序列化为 JSON 文档时, 该格式由 "application/problem+json" 媒体类型标识.
例如, 一个携带 JSON 问题详情的 HTTP 响应如下:
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Content-Language: en
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/msgs/abc",
"balance": 30,
"accounts": ["/account/12345",
"/account/67890"]
}
在这里, 余额不足问题 (由其类型 URI 标识) 在 "title" 中说明 403 的原因, 使用 "instance" 给出该具体问题发生实例的引用, 在 "detail" 中给出针对该发生实例的详细信息, 并添加两个扩展; "balance" 表示账户余额, "accounts" 给出可以充值该账户的链接.
传递问题专用扩展的能力允许表达多个问题. 例如:
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
Content-Language: en
{
"type": "https://example.net/validation-error",
"title": "Your request parameters didn't validate.",
"invalid-params": [ {
"name": "age",
"reason": "must be a positive integer"
},
{
"name": "color",
"reason": "must be 'green', 'red' or 'blue'"}
]
}
注意, 这要求每个子问题足够相似, 可以使用相同的 HTTP 状态码. 如果不能满足这一点, 可以使用 207 (Multi-Status) [RFC4918] 状态码来封装多个状态消息.
3.1. Problem Details 对象成员
问题详情对象可以具有以下成员:
-
type(字符串) - 用于标识问题类型的 URI 引用 [RFC3986]. 本规范鼓励该 URI 在被解引用时提供该问题类型的人类可读文档 (例如使用 HTML [W3C.REC-html5-20141028]). 当该成员不存在时, 其值假定为 "about:blank". -
title(字符串) - 问题类型的简短、人类可读摘要. 除本地化目的外 (例如使用主动内容协商; 见 [RFC7231] 第 3.4 节), 它不应在同一问题的不同发生实例之间变化. -
status(数字) - 源服务器为该问题发生实例生成的 HTTP 状态码 ([RFC7231] 第 6 节). -
detail(字符串) - 针对该问题发生实例的人类可读解释. -
instance(字符串) - 标识该具体问题发生实例的 URI 引用. 解引用它时可能会也可能不会产生进一步信息.
消费者必须使用 "type" 字符串作为问题类型的主要标识符; "title" 字符串只是建议性信息, 仅面向不了解 URI 语义且无法发现这些语义的用户 (例如离线日志分析). 消费者不应自动解引用类型 URI.
如果存在 "status" 成员, 它只是建议性的; 它传递 HTTP 状态码是为了方便消费者. 生成者必须在实际 HTTP 响应中使用相同状态码, 以确保不理解该格式的通用 HTTP 软件仍能正确工作. 关于其使用的进一步注意事项见第 5 节.
在状态码已被更改的情况下 (例如被中间设备或缓存更改), 以及消息体在没有 HTTP 信息的情况下仍被保留时, 消费者可以使用 status 成员确定生成者最初使用的状态码. 通用 HTTP 软件仍会使用 HTTP 状态码.
如果存在 "detail" 成员, 它应重点帮助客户端纠正问题, 而不是提供调试信息.
消费者不应解析 "detail" 成员来提取信息; 扩展是获取此类信息的更合适且更不易出错的方式.
注意, "type" 和 "instance" 都接受相对 URI; 这意味着必须按照 [RFC3986] 第 5 节, 相对于文档的基 URI 对其进行解析.
3.2. 扩展成员 (Extension Members)
问题类型定义可以使用附加成员扩展问题详情对象.
例如, 上面的 "out of credit" 问题定义了两个此类扩展 -- "balance" 和 "accounts", 用于传递额外的问题专用信息.
消费问题详情的客户端必须忽略任何无法识别的此类扩展; 这允许问题类型演进并在未来包含附加信息.
注意, 由于扩展实际上由问题类型放入命名空间中, 因此不可能在不定义新媒体类型的情况下定义新的"标准"成员.