如何使用ijson / other来解析这个大型JSON文件?

时间:2017-12-12 19:21:10

标签: json python-3.x data-structures ijson

我有这个庞大的json文件(8gb),当我尝试将其读入Python时,我的内存不足。我如何使用ijson或其他一些对大型json文件更有效的库来实现类似的过程?

import pandas as pd

#There are (say) 1m objects - each is its json object - within in this file. 
with open('my_file.json') as json_file:      
    data = json_file.readlines()
    #So I take a list of these json objects
    list_of_objs = [obj for obj in data]

#But I only want about 200 of the json objects
desired_data = [obj for obj in list_of_objs if object['feature']=="desired_feature"]

我如何使用ijson或类似的东西实现这个?有没有办法可以在不读取整个JSON文件的情况下提取我想要的对象?

该文件是一个对象列表,如:

{
    "review_id": "zdSx_SD6obEhz9VrW9uAWA",
    "user_id": "Ha3iJu77CxlrFm-vQRs_8g",
    "business_id": "tnhfDv5Il8EaGSXZGiuQGg",
    "stars": 4,
    "date": "2016-03-09",
    "text": "Great place to hang out after work: the prices are decent, and the ambience is fun. It's a bit loud, but very lively. The staff is friendly, and the food is good. They have a good selection of drinks.",
    "useful": 0,
    "funny": 0,
}

2 个答案:

答案 0 :(得分:1)

  

该文件是一个对象列表

这有点模棱两可。查看代码片段,看起来您的文件在每行上都包含单独的JSON对象。这与以-Werror开头的实际JSON数组不同,以[结尾且项目之间有]

对于每行json文件,它就像:

一样简单
,

请注意差异:

  • 您不需要import json from itertools import islice with(open(filename)) as f: objects = (json.loads(line) for line in f) objects = islice(objects, 200) ,文件对象本身是一个可以产生单独行的迭代
  • 括号.readlines()而不是(..)中的括号[..]创建一个惰性生成器表达式,而不是内存中包含所有行的Python列表
  • (... for line in f)将为您提供前200个项目,而无需进一步迭代。如果islice(objects, 200)成为列表,您可以objects

现在,如果你的文件实际上是一个JSON数组,那么你确实需要ijson:

objects[:200]

import ijson # or choose a faster backend if needed from itertools import islice with open(filename) as f: objects = ijson.items(f, 'item') objects = islice(objects, 200) 在解析的数组上返回一个惰性迭代器。第二个参数中的ijson.items表示“顶级数组中的每个项目”。

答案 1 :(得分:0)

问题在于,并非所有JSON都具有良好的格式,您不能依赖逐行解析来提取对象。 我将您的“接受标准”理解为“只想收集指定键包含指定值的JSON对象”。例如,如果该人的姓名为“Bob”,则仅收集有关某人的对象。以下函数将提供符合条件的所有对象的列表。解析是逐个字符完成的(在C中效率更高,但Python仍然相当不错)。这应该更加健壮,因为它不关心换行符,格式化等。我在带有1,000,000个对象的格式化和未格式化的JSON上测试了它。

for (TreeNode child : children) {
    child.setParent(this);
}