2017-10-12 67 views
0

我试图更新一个JSON对象,看起来像这样的密钥的密钥:如何修改的嵌套的Json

results = 
{ 
    'Game':12345, 
    'stats':[ 
     { 
     'detail':[ 
      { 
       'goals':4, 
       'refs':{ 
        'number':0 

我目前手动更新每个键跟随

##update Game to newValue 
results['newValue'] = results['Game'] 
    del results['Game'] 

## update nested key "goals" to "goals_against" 
results['stats'][0]['detail'][0]['goals_against'] = results['stats'][0]['detail'][0]['goals'] 
    del results['stats'][0]['detail'][0]['goals'] 

由于我发现自己必须更新结果中的多个键,因此必须有更好的方法。例如,我也想将“数字”键更新为“assis_ref”。

我懂得,如果是JSON文件是“简单”的更新的关键:即,如果我能做到这一点:

result['stats']['details']['refs'] 

然而,“统计”和“细节”需要[0]旁它我认为是我正在尝试下一步的元素的索引。

+0

的[重命名字典键]可能的复制(https://stackoverflow.com/questions/16475384/rename-a-dictionary-key) – DJV

+1

@DJV它有点不同,因为我试图更新的JSon对象中的密钥是深嵌套的,有时它需要添加下一个节点的索引,例如[0] – jquyl

+0

您可以使用我发布的代码作为[此答案] (http://stackoverflow.com/q/41777880/4014959)为此任务。我几乎将这个问题作为该问题的一个重复来解决,但我认为它有不同之处,因此它应该有自己的答案,所以我会在几分钟后发布一些代码。 –

回答

0

它可能是痛苦的导航和修改从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 
       } 
      ] 
     } 
    ] 
}