为什么python json解码器会抛出带有UTF-16 BOM的字符串?

为什么python json解码器会抛出带有UTF-16 BOM的字符串?,python,json,encoding,utf-8,Python,Json,Encoding,Utf 8,通过深入研究python json解码器实现,我注意到如果一个字符串被传递到json.loads,并且它以\ufeff开头,这是一个错误,它会引发一个JSONDecodeError: if isinstance(s, str): if s.startswith('\ufeff'): raise JSONDecodeError("Unexpected UTF-8 BOM (decode using utf-8-sig)", s, 0) () (UTF-8一)说明了两种情况

通过深入研究python json解码器实现,我注意到如果一个字符串被传递到
json.loads
,并且它以
\ufeff
开头,这是一个错误,它会引发一个
JSONDecodeError

if isinstance(s, str):
    if s.startswith('\ufeff'):
        raise JSONDecodeError("Unexpected UTF-8 BOM (decode using utf-8-sig)", s, 0)
()

(UTF-8一)说明了两种情况下UTF-16 BOM应该被禁止,但它们似乎都不适用于JSON:

o协议应禁止使用U+FEFF作为这些协议的签名 协议要求始终保持的文本协议元素 UTF-8,签名功能在这些应用程序中完全无用 案例

o协议还应禁止使用U+FEFF作为 协议提供的那些文本协议元素 字符编码识别机制,当需要时 协议的实现将能够 始终正确使用机械装置。这种情况将在 协议元素在 从创建之时到发布之时的实施 它们的(正确标记的)传输

(JSON one)说:

JSON文本应采用UTF-8、UTF-16或UTF-32编码。这个 默认编码为UTF-8,JSON文本以UTF-8编码 从成功读取的意义上讲,它们是可互操作的 按实现的最大数量;有很多 无法成功读取其他文件中文本的实现 编码(如UTF-16和UTF-32)

所以在我看来,UTF-16应该被允许。那么为什么Python会在这里出现呢?很明显,我遗漏了一些东西。

来自:

实现不得在网络传输的JSON文本的开头添加字节顺序标记(U+FEFF)。为了实现互操作性,解析JSON文本的实现可能会忽略字节顺序标记的存在,而不是将其视为错误

类似的语言也出现在电影中


接受字节顺序标记不需要JSON实现。Python的实现并没有这样做。如果要将带有字节顺序标记的JSON传递给Python的JSON解析器,则应该在早期处理阶段删除BOM。

您似乎混淆了哪个RFC用于UTF-8,哪个用于JSON。另外,Python3
str
表示编码独立的Unicode。经过更多的阅读,它变得更加清晰。python json解析器拒绝它在accepted answer-spec中正确声明的BOM的主要原因是允许它这样做的,所以这个解析器会这样做。让我困惑的是,我认为有两个BOM,UTF-8和UTF-16,解析器拒绝了UTF-16一个,同时声明它拒绝了UTF-8一个。事实上,只有一个BOM,U+FEFF,\xef\xbb\xbf版本只是它的UTF-8编码。因此,我现在理解的代码背后的逻辑是:[续][续]:如果字符串以BOM开头,那么它必须是未剥离的UTF-8 one,因为如果它是UTF-16 one,它将在读取时剥离。如果它幸存下来,那么产生传递字符串的字节将被编码为UTF-8,并在不剥离BOM的情况下进行解码。这就是为什么异常也告诉“使用utf-8-sig解码”。这在我看来似乎是规范中的一个错误。
U+FEFF
的正式定义不是字节顺序标记,而是一个。JSON应该像对待任何其他空白一样对待它。@markransem:JSON特别指出了“不重要的空白”中允许的四个空白字符:空格、水平制表符、换行符和回车符。字符串之外的其他空格是错误的。是的,它是错误的,我相信空格列表是不必要的限制。如果您只打算使用它的ASCII子集,那么为什么还要麻烦使用基于Unicode的呢?谢谢。这本身就回答了问题,但起初我还是感到困惑。事实上,您在关于编码独立Unicode的原始问题下的评论有助于澄清更多的问题!:)