2017-10-03 17 views
1

JSONツリー構造の各ブランチを、そのブランチ内のアイテムのリストに変換したいとします。私はループを使用してそれをしたいが、私はインデックスを使用してオブジェクトにアクセスすることはできません。JSONツリーの各ブランチをアイテムのリストに変換するにはどうすればいいですか?

Example JSON: 
{ 
    "Root": { "child1": "abc", 
       "child2": "def", 
       "child3": { "grandchild1": "nick", 
          "grandchild2": "Sam" 
         } 
      } 
} 

私はそれらを横断し、以下のようにそれらを保存する:次のように

list1 = ['Root', "child1", "abc"] 
list2 = ['Root', "child2", "def"] 
list3 = ['Root', "child3", "grandchild1", "nick",] 
list4 = ['Root', "child3", "grandchild2", "sam",] 

私はJSONをお読みください。

import json 

with open('sample.json') as f: 
    tree = json.load(f) 

問題:私はこれらをループしたかった アイテムを追加してさまざまなリストに追加しますが、私はtree['Root']のように自分のキーからアクセスできるのはChild1、2、3、tです鶏tree['Root']['child3']は私に他の2人のメンバーを与えるはずです。しかし、このメソッドはJSONファイルに1400個のブランチ(かなり深く入れ子になっている)があり、それらに対して1400個のリストを作成したいというユースケースではスケーラブルではありません。

これを効率的に行う方法はありますか?

+0

は、構造内のすべての値がいずれかの文字列またはオブジェクト(辞書)であることを行っていますか? – glibdud

+0

@glibdudすべての要素はdictですが、dict内の特定のキーの値のいくつかはリストになります。 – utengr

答えて

5

のPython 3.3+と再帰関数からyield fromステートメントを使用:

tree = { 
"Root": { "Child1": "abc", 
      "Child2": "def", 
      "Child3": { "grandchild1": "nick", 
         "grandchild2": "Sam" 
        } 
     } 
} 

def walk_json(tree, path=[]): 
    try: 
     for root, child in tree.items(): 
      yield from walk_json(child, path + [root]) 
    except AttributeError: # in case .items() is not possible (on leaves) 
     yield path + [tree] 

list(walk_json(tree)) 

意志出力:

[['Root', 'Child1', 'abc'], 
['Root', 'Child2', 'def'], 
['Root', 'Child3', 'grandchild1', 'nick'], 
['Root', 'Child3', 'grandchild2', 'Sam']] 
+2

丁寧な回答ですが、「除外:」はむしろトラブルシューティングを困難にする可能性があります。おそらく 'except AttributeError:'を使う方が良いでしょう。 – glibdud

+0

@glibdud:非常にTrue、固定 – Guillaume

+0

@Guillaumeはうまく動作します。私は答えを受け入れましたが、あなたが陳述書からの利回りの基本的な説明を加えることができれば、他の人にとっては素晴らしいことになります。 – utengr

関連する問題