Skip to main content

Appendix A. Frequently Asked Questions (常见问题)

A.1 Why Not JSON? (为什么不用JSON?)

早期的结构化字段提案基于JSON [RFC8259]。然而,约束其使用以使其适合HTTP头部字段需要发送者和接收者实现特定的额外处理。

问题1: 规范问题

JSON在大数字和具有重复成员的对象方面存在规范问题。

// 问题: 大数字
{"value": 9007199254740993} // 超过JavaScript安全整数范围

// 问题: 重复键
{"key": "value1", "key": "value2"} // 行为未定义

虽然有避免这些问题的建议(例如,[RFC7493]),但无法可靠依赖。

问题2: Unicode字符串

JSON字符串默认是Unicode字符串,这有许多潜在的互操作性问题(例如,在比较中)。

// 不同的Unicode表示可能导致问题
"café" // é as single character
"café" // é as e + combining accent
// 这两个看起来相同但二进制不同

虽然可以建议实现者在不必要的地方避免非ASCII内容,但这很难强制执行。

问题3: 任意嵌套深度

JSON能够将内容嵌套到任意深度。

{
"a": {
"b": {
"c": {
"d": {
// ... 无限深度
}
}
}
}
}

后果:

  • 内存承诺可能不合适(例如,在嵌入式和其他有限的服务器部署中)
  • 需要以某种方式限制它
  • 现有的JSON实现没有这样的限制
  • 即使指定了限制,某些字段定义也可能需要违反它

问题4: 实现诱惑

因为JSON被广泛采用和实现,很难在所有实现中强加额外的约束;某些部署将无法强制执行它们,从而损害互操作性。

简而言之: 如果它看起来像JSON,人们会倾向于在字段值上使用JSON解析器/序列化器。

结论

由于结构化字段的主要目标是改进互操作性和简化实现,这些担忧导致采用了需要专用解析器和序列化器的格式。

此外,有广泛共识认为JSON在HTTP字段中"看起来不对"。


对比总结

特性JSONRFC 8941
数字范围不确定(依赖实现)明确定义(15位整数)
小数精度不确定3位小数
Unicode默认支持仅ASCII(可用Byte Sequence)
嵌套深度无限制限制为2层
重复键未定义明确禁止
类型系统宽松严格
解析器复杂度高(需要额外约束)中(专用但简单)
HTTP适配优秀

实际示例

JSON方式(问题)

Example-Header: {"priority": 1, "timeout": 3.14159, "enabled": true}

问题:

  • 需要JSON解析器
  • 小数精度不确定
  • 如果使用Unicode会有问题
  • 在HTTP头部中显得冗长

结构化字段方式(解决方案)

Example-Dict: priority=1, timeout=3.142, enabled

优点:

  • 简洁明了
  • 精度明确(3位小数)
  • 仅ASCII
  • 看起来"属于"HTTP头部

其他被考虑的格式

1. XML

  • 太冗长
  • 解析复杂
  • 不适合简单的键值对

2. Protocol Buffers

  • 需要schema
  • 二进制格式(不适合HTTP/1.1文本头部)
  • 过于复杂

3. MessagePack

  • 二进制格式
  • 不适合HTTP/1.1
  • Base64编码会抵消大小优势

关键要点

  1. JSON不够严格: 对于HTTP头部需要太多额外约束
  2. 互操作性优先: 专用格式确保一致性
  3. 实现现实: 人们会使用通用JSON解析器,破坏严格性
  4. 外观重要: 字段值应该"看起来"属于HTTP
  5. 未来友好: 设计允许二进制编码(HTTP/2、HTTP/3)

引用

"If it looks like JSON, people will be tempted to use a JSON parser/serializer on field values."

—— RFC 8941

这总结了为什么需要不同格式的核心原因。