pythonic迭代存储在文本文件中的json对象集合的方法

时间:2015-07-01 14:21:14

标签: python json

我有一个文本文件,一个接一个地有几千个json对象(意思是json的文本表示)。他们没有分开,我宁愿不修改源文件。如何在python中加载/解析每个json? (我见过this question,但是如果我没弄错的话,这只适用于jsons列表(用逗号隔开?)我的文件看起来像这样:

{"json":1}{"json":2}{"json":3}{"json":4}{"json":5}...

5 个答案:

答案 0 :(得分:1)

如果不使用真正的JSON解析器,我没有看到干净的方法。修改文本和使用非JSON解析器的其他选项都存在风险。因此,最好的方法是找到一种使用真正的JSON解析器进行迭代的方法,以便您确保遵守JSON规范。

核心思想是让真正的JSON解析器完成识别组的所有工作:

Factory function

输出:

import json, re

combined = '{"json":1}{"json":2}{"json":3}{"json":4}{"json":5}'

start = 0
while start != len(combined):
    try:
        json.loads(combined[start:])
    except ValueError as e:
        pass
    # Find the location where the parsing failed
    end = start + int(re.search(r'column (\d+)', e.args[0]).group(1)) - 1
    result = json.loads(combined[start:end])
    start = end
    print(result)

答案 1 :(得分:1)

我认为只要在任何最外面的json对象中没有非逗号分隔的json子对象的json数组,以下内容就会起作用。它有点暴力,因为它将整个文件读入内存并尝试修复它。

import json

def get_json_array(filename):
    with open(filename, 'rt') as jsonfile:
        json_array = '[{}]'.format(jsonfile.read().replace('}{', '},{'))
        return json.loads(json_array)

for obj in get_json_array('multiobj.json'):
    print(obj)

输出:

{u'json': 1}
{u'json': 2}
{u'json': 3}
{u'json': 4}
{u'json': 5}

答案 2 :(得分:0)

不要修改源文件,只需复制即可。使用正则表达式将}{替换为},{,然后希望预先构建的json阅读器可以很好地处理它。

编辑:快速解决方案:

from re import sub

with open(inputfile, 'r') as fin:
    text = sub(r'}{', r'},{', fin.read())
with open(outfile, 'w' as fout:
    fout.write('[')
    fout.write(text)
    fout.write(']')

答案 3 :(得分:0)

>>> import ast
>>> s = '{"json":1}{"json":2}{"json":3}{"json":4}{"json":5}'
>>> [ast.literal_eval(ele + '}') for ele in s.split('}')[:-1]]
[{'json': 1}, {'json': 2}, {'json': 3}, {'json': 4}, {'json': 5}]

如果您没有嵌套对象,并且在'}'上拆分是可行的,这可以非常简单地完成。

答案 4 :(得分:0)

这是一种pythonic方式:

from json.scanner import make_scanner
from json import JSONDecoder

def load_jsons(multi_json_str):
    s = multi_json_str.strip()
    scanner = make_scanner(JSONDecoder())
    idx = 0
    objects = []
    while idx < len(s):
       obj, idx = scanner(s, idx)
       objects.append(obj)
    return objects

我认为json永远不应该以这种方式使用,但它解决了你的问题。

我同意@Raymond Hettinger,您需要使用json本身来完成工作,文本操作不适用于复杂的JSON对象。他的回答解析了异常消息以找到分割位置。它工作,但它看起来像一个黑客,因此,而不是pythonic:)

编辑: 刚发现这实际上是由json模块支持的,只需使用raw_decode,如下所示:

decoder = JSONDecoder()
first_obj, remaining = decoder.raw_decode(multi_json_str)

阅读http://pymotw.com/2/json/index.html#mixed-data-streams