2017-10-12 70 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 
       } 
      ] 
     } 
    ] 
}