很多人会用到JSON格式的数据,但是如果想取得JSON数据中的某个键内容,就必须要一层层往下套取才能拿到,如果层次非常多的话,套取将会非常的麻烦。
比如随意编写的JSON内容,想取得相应的值会非常麻烦,在获取请求的数据时,数组内容的数据可能会不同,无法准确定位到底是哪个目录,如果后期目录修改了,我们也需要重新修改操作目录,将会变得非常麻烦。
{
"errcode":0,
"errmsg":"ok",
"info":{
"sp_no":"202203030015",
"sp_name":"风险",
"sp_status":3,
"template_id":"tetefdfdfdfefsfdfssa",
"apply_time":1614759,
"applyer":{
"userid":"3940",
"partyid":"2"
},
"sp_record":[
{
"sp_status":3,
"approverattr":1,
"details":[
{
"approver":{
"userid":"3940"
},
"speech":"",
"sp_status":3,
"sptime":1614756,
"media_id":[
]
}
]
},
{
"sp_status":1,
"approverattr":1,
"details":[
{
"approver":{
"userid":"5"
},
"speech":"",
"sp_status":1,
"sptime":0,
"media_id":[
]
}
]
}
],
"notifyer":[
],
"apply_data":{
"contents":[
{
"control":"Table",
"id":"Table-1614750144354",
"title":[
{
"text":"测试",
"lang":"zh_CN"
}
],
"value":{
"tips":[
],
"members":[
],
"departments":[
],
"files":[
],
"children":[
{
"list":[
{
"control":"Date",
"id":"Date-1614750",
"title":[
{
"text":"日期",
"lang":"zh_CN"
}
],
"value":{
"tips":[
],
"members":[
],
"departments":[
],
"date":{
"type":"day",
"s_timestamp":"1600000000000"
},
"files":[
],
"children":[
],
"stat_field":[
],
"sum_field":[
],
"related_approval":[
],
"students":[
],
"classes":[
],
"docs":[
],
"wedrive_files":[
]
}
},
{
"control":"Text",
"id":"Text-1614",
"title":[
{
"text":"测试2",
"lang":"zh_CN"
}
],
"value":{
"text":"abcd",
"tips":[
],
"members":[
],
"departments":[
],
"files":[
],
"children":[
],
"stat_field":[
],
"sum_field":[
],
"related_approval":[
],
"students":[
],
"classes":[
],
"docs":[
],
"wedrive_files":[
]
}
},
{
"control":"Textarea",
"id":"Textarea-1614",
"title":[
{
"text":"描述",
"lang":"zh_CN"
}
],
"value":{
"text":"点点滴滴",
"tips":[
],
"members":[
],
"departments":[
],
"files":[
],
"children":[
],
"stat_field":[
],
"sum_field":[
],
"related_approval":[
],
"students":[
],
"classes":[
],
"docs":[
],
"wedrive_files":[
]
}
},
{
"control":"File",
"id":"File-16147",
"title":[
{
"text":"关联附件",
"lang":"zh_CN"
}
],
"value":{
"tips":[
],
"members":[
],
"departments":[
],
"files":[
{
"file_id":"fdfdfdafdfdfdsfdassfdfadfaafafasffasfasffsdafsfsffasfsdfas"
}
],
"children":[
],
"stat_field":[
],
"sum_field":[
],
"related_approval":[
],
"students":[
],
"classes":[
],
"docs":[
],
"wedrive_files":[
]
}
},
{
"control":"RelatedApproval",
"id":"Relatal-161",
"title":[
{
"text":"关联",
"lang":"zh_CN"
}
],
"value":{
"tips":[
],
"members":[
],
"departments":[
],
"files":[
],
"children":[
],
"stat_field":[
],
"sum_field":[
],
"related_approval":[
{
"template_names":[
{
"text":"测试",
"lang":"zh_CN"
}
],
"sp_status":1,
"name":"张三",
"create_time":1611713200,
"sp_no":"202201260001"
}
],
"students":[
],
"classes":[
],
"docs":[
],
"wedrive_files":[
]
}
}
]
}
],
"stat_field":[
],
"sum_field":[
],
"related_approval":[
],
"students":[
],
"classes":[
],
"docs":[
],
"wedrive_files":[
]
}
}
]
},
"comments":[
{
"commentUserInfo":{
"userid":"3940"
},
"commenttime":16147,
"commentcontent":"是,请xxx ",
"commentid":"69358",
"media_id":[
]
}
]
}
}
正常情况下,我们是通过Test['info']['apply_data']['contents'][0]['value']['children'][0]['list'][3]['title'][0]['text']抓取数据,如果抓取数据不存在,则直接报错,当然,我们可以使用get方式去抓取,如果没有直接返回空,这样其实意义不大,所以我后面写了这个代码,可以随意获取相关JSON数据的健对应的值。
它可以直接返回你需要获取的健对应的层级目录,不需要专门去编写相关目录,就能通过该目录获取相关层级的其他目录
比如,我想获取JSON数据中,指定key为:text,值为:关联的附件,然后就能获取当前层级下的节点内容了,其中”['title'][0]['text']“是排除,如果使用则排除这些节点,不使用则返回完整的JSON目录。
dict1 = get_json_to_dict(detail, 'text', '关联附件', len("['title'][0]['text']"))
通过上面的函数就能获取到这个JSON目录"['info']['apply_data']['contents'][0]['value']['children'][0]['list'][3]['title'][0]['text']",如果加了排除,则直接返回这个目录['info']['apply_data']['contents'][0]['value']['children'][0]['list'][3],最终调用处返回这个目录对应的JSON对象内容,非常方便的解决了我们自己写目录的烦恼,也不怕目录改动,因为它能自动找到自己需要的键值的相关目录了
有了这个字典,我就能获取指定字典的相关值,而我编写的这个方法,也能获取相关健值,如获取相关的all_file_id,整体只需要使用两个方法就能解决问题。
如下是具体的代码片段:
loc = locals() # 获取本地资源
def get_var_name(var):
"""
通过变量进行获取当前变量的名称
"""
for k, v in loc.items():
if loc[k] is var:
return k
# 后面是具体编写的JSON获取代码
get_key_list = [] # 共用的循环列表
def get_json_key_value(json_object, key_name, key_value):
"""
获取相关JSON数据的键值进行对比,并返回相关的节点内容
"""
if isinstance(json_object, dict): # 字典
for x in range(len(json_object)):
key_tmp = list(json_object.keys())[x]
value_tmp = json_object[key_tmp]
if len(key_value) == 0:
if key_name == key_tmp:
get_key_list.append(value_tmp)
else:
if key_name == key_tmp and key_value == value_tmp:
return "['" + key_tmp + "']"
result = get_json_key_value(value_tmp, key_name, key_value) # 递归调用
if len(key_value) != 0 and result:
return "['" + key_tmp + "']" + result
elif isinstance(json_object, list): # 列表
ind = -1
for k in json_object:
ind += 1
if isinstance(k, dict):
for x in range(len(k)):
key_tmp = list(k.keys())[x]
value_tmp = k[key_tmp]
if len(key_value) == 0:
if key_name == key_tmp:
get_key_list.append(value_tmp)
else:
if key_name == key_tmp and key_value == value_tmp:
return "[" + str(ind) + "]" + "['" + key_tmp + "']"
result = get_json_key_value(value_tmp, key_name, key_value) # 递归调用
if len(key_value) != 0 and result:
return "[" + str(ind) + "]" + "['" + key_tmp + "']" + result
key_list_tmp = get_key_list.copy()
return key_list_tmp
def get_json_content(json_obj, key_var, value_var):
"""
包装相关JSON返回节点内容,通过键值进行对比,并返回相关的节点内容,如果未找到则返回空
"""
key_value = get_json_key_value(json_obj, key_var, value_var)
if key_value:
return key_value
else:
return ""
def get_json_to_dict(json_obj, key_var, value_var, jump_num):
"""
通过键值内容,获取JSON数据对象的相关字典内容,并返回对应的JSON数据对象,可以通过排除方式进行锁定层级对象
"""
content = get_json_content(json_obj, key_var, value_var)
if content:
if jump_num:
content = content[0:len(content)-int(jump_num)]
try:
result = eval(get_var_name(json_obj) + content)
except:
result = ""
else:
return ""
return result
具体使用代码测试
if __name__ == '__main__':
get_key_list = [] # 执行之前清空一下公共数组
dict1 = get_json_to_dict(detail, 'text', '关联附件', len("['title'][0]['text']")) # 获取指定字典内容
all_file_id = get_json_key_value(dict1, "file_id", "") # 获取指定字典中相关的数据健值
print(all_file_id)