一尘不染

Python:尝试反序列化文件中的多个JSON对象,每个对象跨越多个但行距一致的行

json

好吧,经过将近一个星期的研究,我将向大家介绍一下。我有一个看起来如下的文本文件(以3个单独的json对象为例,但其中有50K):

{
"zipcode":"00544",
"current":{"canwc":null,"cig":7000,"class":"observation"},
"triggers":[178,30,176,103,179,112,21,20,48,7,50,40,57]
}
{
"zipcode":"00601",
"current":{"canwc":null,"cig":null,"class":"observation"},
"triggers":[12,23,34,28,100]
}
{
"zipcode":"00602",
"current":{"canwc":null,"cig":null,"class":"observation"},
"triggers":[13,85,43,101,38,31]
}

我知道如何使用Python
json库处理JSON对象,但是我在如何通过读取文件创建5万个不同的json对象方面遇到了挑战。(也许我什至没有考虑正确,但最终我需要反序列化并加载到数据库中)我尝试过itertools认为自己需要一个生成器,因此可以使用:

with open(file) as f:
    for line in itertools.islice(f, 0, 7): #since every 7 lines is a json object
        jfile = json.load(line)

但是以上内容显然不起作用,因为它没有将7行作为单个json对象读取,而且我也不确定如何在整个文件上进行迭代并加载单个json对象。

以下将给我列出我可以切片的列表:

list(open(file))[:7]

任何帮助将非常感激。


非常接近我的需求,我认为实际上只有一步之遥,但仍然在迭代方面有点挣扎。最终,这将为我提供所有数据帧的迭代打印输出,但是我如何做到这一点,以便我可以捕获所有基本连接在一起的巨型数据帧?然后,我可以将最终的数据帧导出到csv等中。(还有比将它首先创建一个巨大的数据帧更好的方法将此结果上传到数据库中吗?)

def lines_per_n(f, n):
    for line in f:
        yield ''.join(chain([line], itertools.islice(f, n - 1)))

def flatten(jfile):
    for k, v in jfile.items():
        if isinstance(v, list):
            jfile[k] = ','.join(v)
        elif isinstance(v, dict):
            for kk, vv in v.items():
                jfile['%s' % (kk)] = vv
            del jfile[k]
            return jfile

with open('deadzips.json') as f:
    for chunk in lines_per_n(f, 7):
        try:
            jfile = json.loads(chunk)
            pd.DataFrame(flatten(jfile).items())
        except ValueError, e:
            pass
        else:
            pass

阅读 232

收藏
2020-07-27

共1个答案

一尘不染

而是再加载6行,然后将 字符串 传递给json.loads()

with open(file) as f:
    for line in f:
        # slice the next 6 lines from the iterable, as a list.
        lines = [line] + list(itertools.islice(f, 6))
        jfile = json.loads(''.join(lines))

        # do something with jfile

json.load()不仅会吞噬文件中的下一个对象,而且islice(f, 0, 7)只会读取前7行,而不是按7行块读取文件。

您可以在生成器中以大小N的块包装读取文件:

from itertools import islice, chain

def lines_per_n(f, n):
    for line in f:
        yield ''.join(chain([line], itertools.islice(f, n - 1)))

然后使用它来分块您的输入文件:

with open(file) as f:
    for chunk in lines_per_n(f, 7):
        jfile = json.loads(chunk)

        # do something with jfile

另外,如果您的块结果是可变长度的,请阅读直到有可以解析的内容:

with open(file) as f:
    for line in f:
        while True:
            try:
                jfile = json.loads(line)
                break
            except ValueError:
                # Not yet a complete JSON value
                line += next(f)

        # do something with jfile
2020-07-27