它可能是痛苦的导航和修改从JSON对象派生的深层嵌套对象。在Functions that help to understand json(dict) structure我发布了允许您浏览这些对象的代码。请阅读该答案中的解释。在这个答案中,我将展示如何使用该代码修改这些对象中的字典键。
简而言之,find_key
是一个递归生成器,它将查找具有给定名称的所有键。您可以使用next
函数获取第一个(或唯一)匹配的名称。或者在for
循环中调用find_key
,如果您需要使用具有相同名称的多个密钥。
find_key
产生的每个值是dict
键的列表,并且列表索引需要达到期望的键。
from json import dumps
def find_key(obj, key):
if isinstance(obj, dict):
yield from iter_dict(obj, key, [])
elif isinstance(obj, list):
yield from iter_list(obj, key, [])
def iter_dict(d, key, indices):
for k, v in d.items():
if k == key:
yield indices + [k], v
if isinstance(v, dict):
yield from iter_dict(v, key, indices + [k])
elif isinstance(v, list):
yield from iter_list(v, key, indices + [k])
def iter_list(seq, key, indices):
for k, v in enumerate(seq):
if isinstance(v, dict):
yield from iter_dict(v, key, indices + [k])
elif isinstance(v, list):
yield from iter_list(v, key, indices + [k])
results = {
"Game": 12345,
"stats": [
{
"detail": [
{
"goals": 4,
"refs": {
"number": 0
}
}
]
}
]
}
# Change oldkey to newkey
oldkey, newkey = 'goals', 'goals_against'
# Find the first occurrence of the oldkey
seq, val = next(find_key(results, oldkey))
print('seq:', seq, 'val:', val)
# Get the object that contains the oldkey
obj = results
for k in seq[:-1]:
obj = obj[k]
# Change the key
obj[newkey] = obj.pop(oldkey)
print(dumps(results, indent=4))
输出
seq: ['stats', 0, 'detail', 0, 'goals'] val: 4
{
"Game": 12345,
"stats": [
{
"detail": [
{
"refs": {
"number": 0
},
"goals_against": 4
}
]
}
]
}
的[重命名字典键]可能的复制(https://stackoverflow.com/questions/16475384/rename-a-dictionary-key) – DJV
@DJV它有点不同,因为我试图更新的JSon对象中的密钥是深嵌套的,有时它需要添加下一个节点的索引,例如[0] – jquyl
您可以使用我发布的代码作为[此答案] (http://stackoverflow.com/q/41777880/4014959)为此任务。我几乎将这个问题作为该问题的一个重复来解决,但我认为它有不同之处,因此它应该有自己的答案,所以我会在几分钟后发布一些代码。 –