ValueError:在读取json文件时解码“字符串”时未配对的高代理

2024-06-01 07:34:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在使用python 3.8.6。在python中读取(数千)个json文件时,我遇到以下错误:

ValueError: Unpaired high surrogate when decoding 'string' on reading json file

在检查其他stackoverflow帖子时,我尝试使用以下解决方案,但没有任何效果:

1) import json
   json.loads('{"":"\\ud800"}')

2) import simplejson
   simplejson.loads('{"":"\\ud800"}')

问题是,在收到此错误后,剩余的json文件不会被读取。有没有办法消除这个错误,这样我就可以读取所有的json文件

我不确定关于这个问题需要提供什么样的信息,所以请随时询问


Tags: 文件importjsonstringon错误whensimplejson
2条回答

Unicode代码点U+D800may only occur as part of a surrogate pair(然后仅采用UTF-16编码)。因此JSON中的字符串(解码后)不是有效的UTF-8

JSON本身可能有效,也可能无效The spec没有提到不匹配代理项对的情况,但明确允许不存在代码点:

To escape a code point that is not in the Basic Multilingual Plane, the character may be represented as a twelve-character sequence, encoding the UTF-16 surrogate pair corresponding to the code point. So for example, a string containing only the G clef character (U+1D11E) may be represented as "\uD834\uDD1E". However, whether a processor of JSON texts interprets such a surrogate pair as a single code point or as an explicit surrogate pair is a semantic decision that is determined by the specific processor.

Note that the JSON grammar permits code points for which Unicode does not currently provide character assignments.

现在,你可以选择你的朋友,但你不能选择你的家人,你也不能总是选择你的朋友。所以下一个问题是:如何解析这个混乱

看起来Python(版本3.9)中的内置json模块和simplejson(版本3.17.2)解析JSON都没有问题。只有尝试使用字符串时,才会出现此问题。因此,这实际上与JSON没有任何关系:

>>> bork = '\ud800'
>>> bork
'\ud800'
>>> print(bork)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'utf-8' codec can't encode character '\ud800' in position 0: surrogates not allowed

幸运的是,我们可以手动编码字符串并告诉Python如何处理错误。例如,用问号替换错误的代码点:

>>> bork.encode('utf-8', errors='replace')
b'?'

文档中列出了errors参数的other possible options

为了修复这个断开的字符串,我们可以编码(到bytes),然后解码(回到str):

>>> bork.encode('utf-8', errors='replace').decode('utf-8')
'?'

孤立的Unicode surrogate与任何内容都不对应。每个有效的高代理代码点需要紧接着一个低代理代码点,然后才能对其进行有意义的解码

错误消息仅仅意味着此代码点没有明确定义的含义。这就像说“拿”而不说我们应该拿什么,或者“看”而不填句子的宾语

您不应该在不包含UTF-16的文件中使用代理项;它们是为这种编码严格保留的。它用于对16位空间之外的字符进行编码,这种16位编码可以通过在两个代码点上拆分字符的方式自然表示

简单而明显的解决办法是提供丢失的信息,但我们不知道它是什么。也许您有更多的上下文,可以使用正确的低代理项对进行填充。但例如,这是可行的:

>>> json.loads('{"":"\\ud800\\udc00"}')
{'': '𐀀'}

它用单个代码点U+010000填充JSON,但是我们当然不知道这是否是数据应该包含的代码点

相关问题 更多 >