使用python ijson读取一个大的唯一json文件

时间:2018-03-06 23:17:56

标签: python json python-2.7 ijson

我正在尝试解析一个大的json文件(数百个演出)来从其键中提取信息。为简单起见,请考虑以下示例:

import random, string

# To create a random key 
def random_string(length):
        return "".join(random.choice(string.lowercase) for i in range(length))

# Create the dicitonary 
dummy = {random_string(10): random.sample(range(1, 1000), 10) for times in range(15)}

# Dump the dictionary into a json file 
with open("dummy.json", "w") as fp:
        json.dump(dummy, fp)

然后,我在python 2.7中使用ijson来解析文件:

file_name = "dummy.json"

with open(file_name, "r") as fp:

    for key in dummy.keys():

        print "key: ", key 

        parser = ijson.items(fp, str(key) + ".item")

        for number in parser:
            print number,

我期待检索与dic的键对应的列表中的所有数字。但是,我得到了

  

IncompleteJSONError:不完整的JSON数据

我知道这篇文章:Using python ijson to read a large json file with multiple json objects,但在我的情况下,我有一个单独的json文件,形式良好,具有相对简单的模式。关于如何解析它的任何想法?谢谢。

3 个答案:

答案 0 :(得分:0)

ijson 有一个迭代器接口来处理大型JSON文件,允许懒惰地读取文件,以便您可以在小块中处理它并在其他地方保存结果。

您需要使用方法ijson.parse(),它会生成三个值prefix, event, value

一些JSON:

{
    "europe": [
      {"name": "Paris", "type": "city"},
      {"name": "Rhein", "type": "river"}
    ]
  }

<强>代码:

import ijson


data = ijson.parse(open(FILE_PATH, 'r'))

for prefix, event, value in data:
    if event == 'string':
        print(value)

<强>输出:

Paris
city
Rhein
river

参考:https://pypi.python.org/pypi/ijson/

答案 1 :(得分:0)

样本json内容文件如下:它包含两个人的记录。它也可能有200万条记录。

    [
      {
        "Name" : "Joy",
        "Address" : "123 Main St",
        "Schools" : [
          "University of Chicago",
          "Purdue University"
        ],
        "Hobbies" : [
          {
            "Instrument" : "Guitar",
            "Level" : "Expert"
          },
          {
            "percussion" : "Drum",
            "Level" : "Professional"
          }
        ],
        "Status" : "Student",
        "id" : 111,
        "AltID" : "J111"
      },
      {
        "Name" : "Mary",
        "Address" : "452 Jubal St",
        "Schools" : [
          "University of Pensylvania",
          "Washington University"
        ],
        "Hobbies" : [
          {
            "Instrument" : "Violin",
            "Level" : "Expert"
          },
          {
            "percussion" : "Piano",
            "Level" : "Professional"
          }
        ],
        "Status" : "Employed",
        "id" : 112,
        "AltID" : "M112"
      }
      }
    ]

我创建了一个生成器,该生成器将每个人的记录作为json对象返回。代码如下所示。这不是生成器代码。更改几行将使其成为一个生成器。

import json

curly_idx = []
jstr = ""
first_curly_found = False
with open("C:\\Users\\Rajeshs\\PycharmProjects\\Project1\\data\\test.json", 'r') as fp:
    #Reading file line by line
    line = fp.readline()
    lnum = 0
    while line:
        for a in line:
            if a == '{':
                curly_idx.append(lnum)
                first_curly_found = True
            elif a == '}':
                curly_idx.pop()

        # when the right curly for every left curly is found,
        # it would mean that one complete data element was read
        if len(curly_idx) == 0 and first_curly_found:
            jstr = f'{jstr}{line}'
            jstr = jstr.rstrip()
            jstr = jstr.rstrip(',')
            jstr[:-1]
            print("------------")
            if len(jstr) > 10:
                print("making json")
                j = json.loads(jstr)
            print(jstr)
            jstr = ""
            line = fp.readline()
            lnum += 1
            continue

        if first_curly_found:
            jstr = f'{jstr}{line}'

        line = fp.readline()
        lnum += 1
        if lnum > 100:
            break

答案 2 :(得分:0)

您正在使用同一文件对象启动多个解析迭代,而没有对其进行重置。首次调用ijson可以,但是会将文件对象移动到文件末尾;那么第二次将same.object传递给ijson时,它将抱怨,因为不再有文件可读取。

每次调用ijson时尝试打开文件;或者,您可以在调用ijson之后搜索文件的开头,以便文件对象可以再次读取文件数据。