一日一技:如何正确解析超大JSON列表
摄影:产品经理
回锅肉
当我们采购数据集时,有时候供应商会以JSON Lines的形式交付给我们。这种格式,本质上是文本格式,它每一行是一个JSON。例如,供应商给我们了一个文件小红书全量笔记.json
文件,我们可以使用如下Python代码来一行一行读取:
1 | import json |
这个格式的好处在于,每一次只需要把少量内容读取到内存中。即便这个文件有1TB,我们也可以使用一个4GB内存的电脑来处理。
今天出了一个乌龙事件,某数据供应商在给我数据的时候,说的是以JSON Lines格式给我。但我拿过来解压缩以后一看,100GB的文件,里面只有1行,如下图所示:
也就是说,他用的是一个超大JSON直接导出给我,并没有使用JSON Lines格式。正常情况下,如果我要直接解析这个数据,需要我的电脑内存超过100GB。
这个大JSON大概格式是这样的:
1 | [{"question": "xxx111", "answer": "aaa", "crawled_time": "2025-05-01 12:13:14"}, {"question": "xxx222", "answer": "aaa", "crawled_time": "2025-05-01 12:13:14"}, {"question": "xxx333", "answer": "aaa", "crawled_time": "2025-05-01 12:13:14"}, ...] |
要解决这个问题,有三种方法。
如果这个JSON里面没有嵌套数据,只有一层key: value
。那么非常简单。一个字符,一个字符读取。遇到}
的时候,说明一条子JSON数据已经读取完成,解析以后再读取下一条子JSON。
如果这个JSON里面有嵌套结构,那么可以使用经典算法题里面的数括号算法来解决。当发现}
的数量等于{
的时候,说明一个子JSON已经读取完成,可以解析了。
今天我们来介绍第三种方法,使用一个第三方库,叫做ijson
。它天然支持解析这种超大的JSON,并且代码非常简单:
1 | import ijson |
运行效果如下图所示:
既不会占用大量内存,又能正常解析超大JSON。