【发布时间】:2018-04-30 19:11:37
【问题描述】:
挖掘python json解码器实现我注意到如果一个字符串被传递给json.loads并且它以\ufeff开头,这是一个UTF-16 BOM,它会引发一个JSONDecodeError:
if isinstance(s, str):
if s.startswith('\ufeff'):
raise JSONDecodeError("Unexpected UTF-8 BOM (decode using utf-8-sig)", s, 0)
(github)
RFC3629(UTF-8 之一)说明了应禁止使用 UTF-16 BOM 的两种情况,但似乎都不适用于 JSON:
o 协议应该禁止使用 U+FEFF 作为签名 协议要求始终包含的文本协议元素 UTF-8,签名功能在那些中完全没用 案例。
o 协议也应该禁止使用 U+FEFF 作为签名 协议提供的那些文本协议元素 字符编码识别机制,当它是预期的 该协议的实现将能够 始终正确使用这些机制。这将是当 协议元素在控制下被严格维护 从创建时间到实施时间 他们的(正确标记的)传输。
RFC7159(JSON 那个)说:
JSON 文本应以 UTF-8、UTF-16 或 UTF-32 编码。这 默认编码为 UTF-8,JSON 文本以 UTF-8 编码 在它们将被成功读取的意义上是可互操作的 按最大实现数;有许多 无法成功读取其他文本的实现 编码(例如 UTF-16 和 UTF-32)。
所以在我看来应该允许使用 UTF-16。那么为什么 Python 会在这里引发呢?显然我错过了一些东西。
【问题讨论】:
-
您似乎混淆了哪个 RFC 用于 UTF-8,哪个 RFC 用于 JSON。此外,Python 3
str表示独立于编码的 Unicode。 -
看多了就明白了。 python json解析器拒绝它在接受的答案中正确陈述的BOM的主要原因 - 规范允许它,所以这个解析器做到了。让我感到困惑的是,我认为有两个 BOM,UTF-8 和 UTF-16,解析器拒绝 UTF-16 一个,同时声明它拒绝 UTF-8 一个。实际上只有一个 BOM,U+FEFF,\xef\xbb\xbf 版本只是它的 UTF-8 编码。所以我现在理解的这段代码背后的逻辑是:[继续]
-
[cont.]:如果一个字符串以 BOM 开头,那么它必须是未剥离的 UTF-8 之一,因为如果它是 UTF-16 之一,它会在读取时被剥离。如果它幸存下来,那么源自传递字符串的字节将以 UTF-8 编码并在不剥离 BOM 的情况下进行解码。这就是为什么异常也会告诉“使用 utf-8-sig 解码”。
标签: python json encoding utf-8