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