Python ijson - 嵌套解析
Python ijson - nested parsing
我正在处理 JSON 的网络响应,看起来像这样(经过简化,我无法更改格式):
[
{ "type": "0","key1": 3, "key2": 5},
{ "type": "1","key3": "a", "key4": "b"},
{ "type": "2", "data": [<very big array here>] }
]
我想做两件事:
- 检查前两个对象而不将所有内容都读入内存,我可以使用 Ijson 做到这一点:
parsed = ijson.items(res.raw, 'item')
next(parsed) # first item
next(parsed) # second item
检查第三个对象而不将其全部放入内存。
如果我再次执行 next(parsed)
,所有“数据”数组将被读取到内存并变成字典,我想避免它。
检查数据数组而不将其全部加载到内存中。如果我不关心其他键,我可以这样做:
parsed = ijson.items(res.raw, 'item.data.item') # iterator over data's items
问题是,我需要在同一流上执行所有这些操作。
理想情况下,接收第三个对象作为我可以再次传递给 ijson 的类文件对象会很棒,但这似乎超出了范围 API。
我也同意用可以更好地完成此操作的库替换 ijson。
您需要使用 ijson 的 event interception mechanism。基本上通过使用 ijson.parse
在解析逻辑中降低一个级别,直到您遇到大数组,然后切换到对其余 parse
事件使用 ijson.items
。这使用字符串文字,但应该说明这一点:
import ijson
s = b'''[
{ "type": "0","key1": 3, "key2": 5},
{ "type": "1","key3": "a", "key4": "b"},
{ "type": "2", "data": [1, 2, 3] }
]'''
parse_events = ijson.parse(s)
while True:
path, name, value = next(parse_events)
# do stuff with path, name, data, until...
if name == 'map_key' and value == 'data':
break
for value in ijson.items(parse_events, 'item.data.item'):
print(value)
我正在处理 JSON 的网络响应,看起来像这样(经过简化,我无法更改格式):
[
{ "type": "0","key1": 3, "key2": 5},
{ "type": "1","key3": "a", "key4": "b"},
{ "type": "2", "data": [<very big array here>] }
]
我想做两件事:
- 检查前两个对象而不将所有内容都读入内存,我可以使用 Ijson 做到这一点:
parsed = ijson.items(res.raw, 'item')
next(parsed) # first item
next(parsed) # second item
检查第三个对象而不将其全部放入内存。 如果我再次执行
next(parsed)
,所有“数据”数组将被读取到内存并变成字典,我想避免它。检查数据数组而不将其全部加载到内存中。如果我不关心其他键,我可以这样做:
parsed = ijson.items(res.raw, 'item.data.item') # iterator over data's items
问题是,我需要在同一流上执行所有这些操作。
理想情况下,接收第三个对象作为我可以再次传递给 ijson 的类文件对象会很棒,但这似乎超出了范围 API。
我也同意用可以更好地完成此操作的库替换 ijson。
您需要使用 ijson 的 event interception mechanism。基本上通过使用 ijson.parse
在解析逻辑中降低一个级别,直到您遇到大数组,然后切换到对其余 parse
事件使用 ijson.items
。这使用字符串文字,但应该说明这一点:
import ijson
s = b'''[
{ "type": "0","key1": 3, "key2": 5},
{ "type": "1","key3": "a", "key4": "b"},
{ "type": "2", "data": [1, 2, 3] }
]'''
parse_events = ijson.parse(s)
while True:
path, name, value = next(parse_events)
# do stuff with path, name, data, until...
if name == 'map_key' and value == 'data':
break
for value in ijson.items(parse_events, 'item.data.item'):
print(value)