我有以下格式的json。
json_tree ={
"Garden": {
"Seaside": {
"@loc": "127.0.0.1",
"@myID": "1.3.1",
"Shoreside": {
"@myID": "3",
"InfoList": {
"Notes": {
"@code": "0",
"@myID": "1"
},
"Count": {
"@myID": "2",
"@val": "0"
}
},
"state": "0",
"Tid": "3",
"Lakesshore": {
"@myID": "4",
"InfoList": {
"Notes": {
"@code": "0",
"@oid": "1"
},
"Count": {
"@myID": "2",
"@val": "0"
}
},
"state": "0",
"Tid": "4"
}
},
"state": "0",
"Tid": "2"
},
"Tid": "1",
"state": "0"
}
}
我的实现:
def getmyID(json_tree, itemList):
for k1, v1 in json_tree .items():
for k,v in v1.items():
if k == itemList:
return '{}{}.{}'.format(json_tree['@myID'] + '.' if '@myID' in json_tree else '',
v['@myID'], v['InfoList']['status']['@myID'])
我的问题是,当我要查找到“ BackYard”的路线时,此方法返回“ None”时不起作用。请注意,“后院”嵌套在“海边”节点内。
我将关键节点的“ @myID”附加到相应“状态”节点中的“ @myID”上。
getmyID(json_tree, "Seaside")
"Output" = "1.2.3.26" --> Currently I get this only
getmyID(json_tree, "BackYard")
"Output" = "1.2.3.75.32" --> expected output but getting "None"
The expected output of "Backyard" is created by concatenating the "@myID" of the root node which it is nested in, that is "Seaside" in this case, and concatenating it with the "@myID" of "backYard" and the "@myID" of its "status" node.
"For a nested node, output string is formed by":
["root @myID" + "nested node "@myID" + "status node @myID"] or ["1.2.3" + "75" + "23"] for "Backyard".
"For a level node, output string is formed by":
["root @myID" + "status node @myID"] or ["1.2.3" + "26"] for "Seaside".
任何帮助将不胜感激。 谢谢。
答案 0 :(得分:1)
您可以将递归与生成器一起使用:
def get_vals(d, target, path = []):
for a, b in d.items():
if a == target:
yield '.'.join(filter(None, path+[b['@myID'], b["InfoList"]['status']['@myID']]))
if isinstance(b, dict):
yield from get_vals(b, target, path + [b.get('@myID', '')])
print(list(get_vals(json_tree, "Seaside")))
print(list(get_vals(json_tree, "BackYard")))
输出:
['1.2.3.26']
['1.2.3.75.32']
编辑:最新数据:
def get_vals(d, target, paths = []):
for a, b in d.items():
if a == target:
yield '.'.join(filter(None, paths+[b["@myID"], b.get("InfoList", {}).get('Notes', {}).get('@myID')]))
if isinstance(b, dict):
yield from get_vals(b, target, paths+[b.get('@myID')])
print(list(get_vals(json_tree, "Seaside")))
print(list(get_vals(json_tree, 'Shoreside')))
输出:
['1.3.1']
['1.3.1.3.1']
答案 1 :(得分:-2)
编辑-只要人们告诉我原因,人们对我的答案不满意甚至编辑都不会有问题。很想听听Yvette Colomb和ChrisF的回音。
这是我使用基于堆栈的方法提出的解决方案。这样做的想法是,在找到所需的键(称为itemList)之前,尝试深入嵌套结构。我确定必须有更简单的方法:
json_tree = {
"Gardens": {
"Seaside": {
"@loc": "porch",
"@myID": "1.2.3",
"Tid": "1",
"InfoList": {
"status": {
"@default": "0",
"@myID": "26"
},
"count": {
"@default": "0",
"@myID": "1"
}
},
"BackYard": {
"@myID": "75",
"Tid": "2",
"InfoList": {
"status": {
"@default": "6",
"@myID": "32"
},
"count": {
"@default": "0",
"@myID": "2"
}
}
}
}
}
}
def is_valid_kv_pair(key, value):
try:
assert isinstance(key, str)
assert isinstance(value, dict)
assert isinstance(value["@myID"], str)
assert isinstance(value["Tid"], str)
assert isinstance(value["InfoList"], dict)
assert isinstance(value["InfoList"]["status"], dict)
assert isinstance(value["InfoList"]["status"]["@default"], str)
assert isinstance(value["InfoList"]["status"]["@myID"], str)
except (AssertionError, KeyError):
return False
else:
return True
def get_id(dictionary, desired_key):
if not isinstance(dictionary, dict):
return None
dictionary_stack = [dictionary]
root_stack = []
while dictionary_stack:
current_dictionary = dictionary_stack.pop()
appended_root = False
for key, value in current_dictionary.items():
if appended_root:
root_stack.pop()
if is_valid_kv_pair(key, value):
if key == desired_key:
rootIDs = [d["@myID"] for d in root_stack]
myID = value["@myID"]
statusID = value["InfoList"]["status"]["@myID"]
return ".".join(rootIDs + [myID] + [statusID])
root_stack.append(value)
appended_root = True
if isinstance(value, dict):
dictionary_stack.append(value)
return None
ID = get_id(json_tree, "BackYard")
print(ID)