使用 ijson 解析大 JSON 时出现“解析错误:不允许的令牌...”

时间:2021-06-24 14:36:45

标签: python json parsing tweets ijson

我正在尝试解析和筛选一个非常大的 JSON 文件,其中包含 9gb 大小的推文元数据。这就是我使用 ijson 的原因,因为这是社区最推荐用于此类文件的一种。它仍然很新,但我设置了这个函数,它应该根据某些条件将值存储到列表中。在循环遍历不同的 JSON 时,它向我显示了以下错误:

parse error: unallowed token at this point in JSON text
          sitive": false, "lang": "en"},  {"created_at": "Thu Mar 19 1
                     (right here) ------^

我不确定我需要更改什么才能使其正常工作。在使用 Twarc 库对推文进行水合后,我得到了这个文件。我在下面附上了我的示例代码。以前有人遇到过这种情况吗?

示例代码:

import ijson

with open(march_20_tweets_path, 'rb') as input_file:
          jsonobj = ijson.items(input_file, 'item', multiple_values=True)
          jsons = (o for o in jsonobj if o['place'] is not None) #error shows here
          for tweet in jsons:
                   #extracting and storing values

1 个答案:

答案 0 :(得分:1)

这可能是(但不一定!)错误编写的“行分隔”JSON 文件。 (yajl 起源,仅由 ijson 显示)错误消息不一定显示原始字符,因此无法立即看出错误的真正原因是什么。

但是,这可以通过一个小示例轻松重现(ijson.dump 仅在 ijson 的 master 版本上可用,尚未发布到 PyPI 上):

$> echo '0,1' | python -m ijson.dump -M
[...]
ijson.common.IncompleteJSONError: parse error: unallowed token at this point in JSON text
                                      0,1 
                     (right here) ------^

这里有两个顶级 JSON 文档,它们由单个值 01 组成。但是,逗号不属于任何一个文档,因此不允许使用标记(即逗号)。

一个更相关的例子:

$> echo '{},{}' | python -m ijson.dump -M
[...]
ijson.common.IncompleteJSONError: parse error: unallowed token at this point in JSON text
                                     {}, {} 
                     (right here) ------^

如果你在中间添加一个新行:

$> echo -e '{},\n\n{}' | python -m ijson.dump -M
[...]
ijson.common.IncompleteJSONError: parse error: unallowed token at this point in JSON text
                                     {},  {} 
                     (right here) ------^

去掉逗号就没有问题了:

$> echo -e '{}\n\n{}' | python -m ijson.dump -M
#: name, value
--------------
0: start_map, None
1: end_map, None
2: start_map, None
3: end_map, None

总结:

  • 很可能“行分隔”JSON 文件不仅由换行符分隔,而且在顶级对象之间还有逗号。
  • 如果确实如此,您可以使用 sed 或类似工具删除文件中的尾随逗号。您甚至可以在命令管道中执行此操作,以避免将结果写回磁盘,例如 sed 's/\(.*\),\s*/\1/' input.json | python your-script.pyyour-script.pysys.stdin.buffer 读取内容。
  • 我可能完全错了,不允许的令牌的来源在其他地方。