首页 > 解决方案 > `JSONDecoder` 如何知道使用哪种编码?

问题描述

像一个好孩子一样阅读了Joel 关于 EncodingJSONDecoder的文章后,我发现自己对 Foundation 的工作方式感到困惑,其initdecode方法都没有编码值。浏览文档,我看到了实例变量dataDecodingStrategy,这也许就是编码猜测魔法发生的地方......?

我在这里错过了什么吗?不需要JSONDecoder知道它接收到的数据的编码吗?我意识到 JSON 标准要求这些数据采用 UTF-8 编码,但可以JSONDecoder做出这样的假设吗?我很困惑。

标签: jsonswift

解决方案


RFC 8259(从 2017 年开始)要求

在不属于封闭生态系统的系统之间交换的 JSON 文本必须使用 UTF-8 编码。

较旧的RFC 7159(从 2013 年开始)和RFC 7158(从 2013 年开始)仅声明

JSON 文本应以 UTF-8、UTF-16 或 UTF-32 编码。默认编码是 UTF-8,并且以 UTF-8 编码的 JSON 文本是可互操作的,因为它们将被最大数量的实现成功读取;有许多实现无法成功读取其他编码(例如 UTF-16 和 UTF-32)的文本。

RFC 4627(从 2006 年开始,我能找到的最古老的):

JSON 文本应以 Unicode 编码。默认编码为 UTF-8。

由于 JSON 文本的前两个字符始终是 ASCII 字符,因此可以通过查看来确定八位字节流是 UTF-8、UTF-16(BE 或 LE)还是 UTF-32(BE 或 LE)前四个八位字节中的空值模式。

JSONDecoderJSONSerialization在引擎盖下使用)能够解码 UTF-8、UTF-16 和 UTF-32,包括 little-endian 和 big-endian。例子:

let data = "[1, 2, 3]".data(using: .utf16LittleEndian)!
print(data as NSData) // <5b003100 2c002000 32002c00 20003300 5d00>

let a = try! JSONDecoder().decode([Int].self, from: data)
print(a) // [1, 2, 3]

由于有效的 JSON 文本必须以“[”或“{”开头,因此可以从数据的第一个字节明确地确定编码。

不过,我没有发现此文档,并且可能不应该依赖它。未来的实现JSONDecoder可能仅支持较新的标准并需要 UTF-8。


推荐阅读