开发过程中,数据处理经常会遇到需要从JSON中取值的情况。对应结构简单的JSON,我们可以像字典那样获取到想要的值;对于结构复杂的多层嵌套的JSON,知道要取值的key的‘路径’的话,也可以使用一些三方库(如jsonpath)来优雅的取到想要的值;但是当我们只知道要取值的key,但是不知道这个key在JSON中具体的‘路径’,该如何获取到想要的值呢?
也许网上有现成的轮子来从深层嵌套的JSON中获取到特定key的value,可惜我不知道,如果有知道的朋友还请评论区留言分享下。现在我们来自己造个轮子。
import json
def json_value_find(json_data, target_key):
def iter_node(node_data):
if isinstance(node_data, dict):
key_value_iter = (x for x in node_data.items())
elif isinstance(node_data, list):
key_value_iter = (x for x in enumerate(node_data))
else:
return
for key, value in key_value_iter:
if key == target_key:
yield value
if isinstance(value, (dict, list)):
yield from iter_node(value)
dict_data = json.loads(json_data)
return list(iter_node(dict_data))
通过以上代码就能获取到JSON中指定key的value了。
我们来试一下效果:
data = """{
"transNo":"1EN03CJS0AH",
"Response":{
"Header":{
"RC":0,
"RM":""
},
"Body":{
"items":[
{
"playStatus":9,
"category":{
"name":"生活",
"code":"ZTPK_SH",
"path":"ZTPK_SH",
"parentCode":"SMG_ZTPK",
"ottSmallImage":"",
"icon1":"/20150409/20150409042255920.png",
"icon2":"",
"icon3":"",
"bigImage1":"",
"bigImage2":"",
"bigImage3":"",
"templateCode":"NEWS",
"hasChild":1
},
"program":{
"name":"建国大业",
"code":"1111",
"icon1":"/20100306/0_20100306080547421.jpg",
"icon2":"/20100306/1_20100306080547562.jpg",
"icon3":null,
"type":0,
"length":8098,
"cpDisplayName":""
},
"program1":{
"name":"建国大业1",
"code":"1111",
"icon1":"/20100306/0_20100306080547421.jpg",
"icon2":"/20100306/1_20100306080547562.jpg",
"icon3":null,
"type":0,
"length":8098,
"cpDisplayName":""
}
}
]
}
}
}"""
获取name所对应的值:
类似的,如果我们只知道key,想要获取这个key在JSON中的‘路径’的话,可以这么操作:
import json
def json_path_find(json_data, target_key):
def iter_node(node_data, road_step):
if isinstance(node_data, dict):
key_value_iter = (x for x in node_data.items())
elif isinstance(node_data, list):
key_value_iter = (x for x in enumerate(node_data))
else:
return
for key, value in key_value_iter:
current_path = road_step.copy()
current_path.append(key)
if key == target_key:
yield current_path
if isinstance(value, (dict, list)):
yield from iter_node(value, current_path)
dict_data = json.loads(json_data)
return list(iter_node(dict_data, []))
这次获取name所对应的路径,效果如下: