我正在尝试解析json以找到所需键的值。我是递归地这样做的。如果有另一种,快速或更有效的方法,我就是开放的
示例json:
{
"data_version":"5",
"application":{
"platform":"iPhone",
"os":"iPhone OS",
"locale":"en_US",
"app_version":"unknown",
"mobile":{
"device":"iPhone",
"carrier":"Verizon",
}
},
"event_header":{
"accept_language":"en-us",
"topic_name":"mobile-clickstream",
"server_timestamp":1416958459572,
"version":"1.0"
},
"session":{
"properties":{
}
},
"event":{
"timestamp":1416958459185,
"properties":{
"event_sequence_number":97
}
}
}
这是我到目前为止所拥有的
def json_scan(json_obj, key):
result = None
for element in json_obj:
if str(element) == key:
result = json_obj[element]
else:
if type(json_obj[element]) == DictType:
json_scan(json_obj[element], key)
elif type(json_obj[element]) == ListType:
json_scan(element, key)
return result
预期产出:
>>> json_scan(json_obj, "timestamp")
1416958459185
当我浏览调试器时,我能够找到所需的值,但是行result = None
将结果重置为None
,并且在方法结束时,我得到的值是{{ 1}}。我不知道如何解决这个问题。我尝试删除该行,但我收到错误,因为结果未预设为值。
答案 0 :(得分:2)
使用json库来解析json文件(应该删除一些逗号)并使用本机dict类型:
def json_scan(json_obj, key):
d = json.loads(json_obj)
def _(dictobj, lookup):
if lookup in dictobj.keys():
return dictobj[lookup]
else:
for sub_dictobj in [d for d in dictobj.values() if type(d) == DictType]:
result = _(sub_dictobj, lookup)
if result:
return result
return None
return _(d, key)
更完整的版本:
def json_scan(json_obj, key):
d = json.loads(json_obj)
def _(dictobj, lookup):
if lookup in dictobj.keys():
return dictobj[lookup]
else:
for sub_dictobj in [d for d in dictobj.values() if type(d) == DictType]:
result = _(sub_dictobj, lookup)
if result:
return result
# if objects in dictobj.values() are lists, go through them
for listobject in [l for l in dictobj.values() if type(d) == list]:
for sub_dictobj in [d for d in listobject if type(d) == DictType]:
result = _(sub_dictobj, lookup)
if result:
return result
return None
return _(d, key)
编辑(2015/04/25):
在看了@ PyCon 2015视频后,我遇到了dict_digger:
http://jtushman.github.io/blog/2013/11/06/dict-digger/ https://github.com/jtushman/dict_digger
它带有测试......
答案 1 :(得分:1)
您应该从if语句中返回结果。所以,你的代码将是:
def json_scan(json_obj, key):
for element in json_obj:
if str(element) == key:
result = json_obj[element]
return result
else:
if type(json_obj[element]) == DictType:
json_scan(json_obj[element], key)
elif type(json_obj[element]) == ListType:
json_scan(element, key)
return None
这样,如果找到结果,它会立即返回,而不是将其重置为无。如果找不到它,它最后仍然会返回None。
答案 2 :(得分:1)
问题是您没有将递归调用分配给结果:
def json_scan(json_obj, key):
result = None
for element in json_obj:
if str(element) == key:
result = json_obj[element]
else:
if type(json_obj[element]) == DictType:
result = json_scan(json_obj[element], key)
elif type(json_obj[element]) == ListType:
result = json_scan(element, key)
return result
另一个问题是你的扫描不适用于列表 - json_obj[element]
只适用于dicts - 但由于你的数据没有列表,它现在正在工作。您应该完全删除列表处理(除非您确实有列表,然后算法需要更改)。