如果错误发生在line 2 column 1,这强烈暗示数据实际上是JSONL(“JSON Lines”)格式--一种相关格式,其中每行输入都是一个单独的JSON实体(通常是一个对象)。只需要遍历输入的行,分别解析每一行,然后把结果放到一个列表中。例如,使用列表解析:[json.loads(line) for line in open_json_file]。有关详细信息,请参阅Loading JSONL file as JSON objects。
>>> import json
>>> example = '{"key": "value"} extra'
>>> json.loads(example) # breaks because of the extra data:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.8/json/__init__.py", line 357, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.8/json/decoder.py", line 340, in decode
raise JSONDecodeError("Extra data", s, end)
json.decoder.JSONDecodeError: Extra data: line 1 column 18 (char 17)
>>> parsed, size = json.JSONDecoder().raw_decode(example)
>>> parsed
{'key': 'value'}
>>> size # amount of text that was parsed.
16
>>> json.loads('"\\ "') # the input string has only one backslash
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.8/json/__init__.py", line 357, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.8/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.8/json/decoder.py", line 353, in raw_decode
obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Invalid \escape: line 1 column 2 (char 1)
1条答案
按热度按时间frebpwbc1#
前言
the decoding code * 明确 * 引发的唯一异常是
json.JSONDecodeError
,因此异常类型无助于诊断问题。有趣的是相关消息。然而,在尝试JSON解码之前,有可能将字节解码为文本失败。这是一个超出本文范围的单独问题。这里值得注意的是,JSON format documentation使用了与Python不同的术语,特别是
{}
中包含的一部分有效JSON数据是一个 object(而不是“dict”),并且包含在[]
中的部分是一个 * 数组 *(而不是“list”)。当谈论文件内容时,我将使用JSON术语,当谈论解析结果或由Python代码直接创建的数据时,我将使用Python术语。作为一般提示:使用专门的JSON查看器来检查文件,或者至少使用具有“平衡”括号功能的文本编辑器(即,假设插入指针当前位于
{
,它将自动找到匹配的}
)。不是JSON
显示
Expecting value
的错误消息强烈表明数据根本不适合JSON格式。请仔细记录错误的行和列位置以获取更多信息:<
开头,则当然建议XML而不是JSON。否则,在实际JSON内容之前可能会有一些填充。有时,在Web环境中这是to implement a security restriction;在其他情况下,它是到work around a different restriction。后一种情况称为JSONP(JSON with Padding)。无论哪种方式,都需要检查数据,以确定在解析之前应该从开头(也可能是结尾)裁剪多少。
repr
,像这样的数据通常可以使用ast.literal_eval
解析,但是它不应该被认为是一种实用的序列化格式-它不能很好地与非Python编写的代码互操作,并且使用repr
可以很容易地产生无法通过这种方式(或任何实际方式)恢复的数据。注意Python的原生对象表示和JSON格式之间的一些共同差异,以帮助诊断问题:
'''example'''
)或三双引号("""example"""
)。true
和false
而不是True
和False
来表示布尔值;使用null
而不是None
作为特殊的“这里没有任何内容”值;使用Infinity
和NaN
而不是inf
和nan
来表示特殊的浮点值。一个微妙之处:
Expecting value
还可以表示数组或对象中的尾随逗号,JSON语法不允许在列出元素或键-值对之后使用尾随逗号,尽管Python允许。尽管逗号是“额外的”,但这将被报告为缺少的东西(下一个元素或键-值对),而不是无关的东西(逗号)。错误消息
Extra data
表示JSON数据末尾之后还有更多文本。[json.loads(line) for line in open_json_file]
。有关详细信息,请参阅Loading JSONL file as JSON objects。JSONDecoder
类的.raw_decode
方法:无效的字符串文字
错误消息指出以下任何一项:
Invalid \\uXXXX escape
Invalid \\escape
Unterminated string starting at
表明数据中的字符串格式不正确,很可能是由于转义码编写不当。
JSON字符串不能包含严格模式下的控制代码(解析时的默认设置),例如,换行符必须用
\n
编码。注意,数据必须实际上包含一个反斜杠;当查看字符串形式的JSON数据的 * 表示 * 时,反斜杠将被加倍(但不是在print
ing字符串时)。JSON不接受Python的
\x
或\U
转义,只接受\u
。要表示BMP之外的字符,请使用代理对:不像Python中的字符串常量,一个反斜杠后面跟着一些不构成有效转义序列的东西(比如空格)将not被接受:
类似地,JSON字符串中的单引号不能转义,但双引号必须转义。
在REPL调试或测试此类问题时,不要混淆JSON的转义和Python的转义,这一点很重要。
错误支架
Expecting ',' delimiter
和Expecting ':' delimiter
意味着用于对象或数组的括号与内容不匹配。例如,像["foo": "bar"]
这样的JSON几乎肯定是用来表示对象的,因此它应该包含{}
而不是[]
。请查看报告错误的行和字符位置,然后向后扫描到包含的括号。但是,这些错误也可能意味着正是他们说:可能只是数组元素或键值对之间缺少逗号,或者键与其值之间缺少冒号。
无效密钥
虽然Python allows anything hashable作为dict键,但JSON需要字符串作为其对象键。这个问题由
Expecting property name enclosed in double quotes
表示。虽然它可能发生在手写JSON中,但它可能暗示了在Python对象上使用repr
创建的数据不合适的问题。(如果在检查文件中的指定位置时,发现有人试图使用单引号中的字符串键,则这种情况尤其可能发生。)错误消息
Expecting property name enclosed in double quotes
* 也 * 可能表示“错误的括号”问题,特别是,如果数据应该是一个包含整数的数组,但被{}
而不是[]
包围,解析器将在其他任何东西之前期待一个双引号字符串键,并抱怨列表中的第一个整数。