У меня огромный JSON в формате что-то вроде:

{
    "Name1": {
        "NNum": "11",
        "Node1": {
            "SubNodeA": "Thomas",
            "SubNodeB": "27"
        },
        "Node2": {
            "SubNodeA": "ZZZ",
            "SubNodeD": "XXX",
            "SubNodeE": "yy"
        },
        "Node3": {
                "child1": 11,
                "child2": {
                    "grandchild": {
                        "greatgrandchild1": "Rita",
                        "greatgrandchild2": "US"
                                }
                            }   
                }
            }
}

Формат или ключи не определены и могут идти на любую глубину, я хотел бы получить список ключей, таких как

keyList= ["Name1.NNum","Name1.Node1.SubNodeA",""Name1.Node1.SubNodeB","Name1.Node2.SubNodeA","Name1.Node2.SubNodeD","Name1.Node2.SubNodeE","Name1.Node3.child1","Name1.Node3.child2.grandchild.greatgrandchild1","Name1.Node3.child2.grandchild.greatgrandchild2"]

Снимок кода

def extract_values(obj):
    """Pull all values of specified key from nested JSON."""
    arr = []
    key_list = []
    parent = ""
    def extract(obj, arr,parent):
        """Recursively search for values of key in JSON tree."""
        if isinstance(obj, dict):
            grandparent = ""
            for k, v in obj.items():
                print ("k ............",k)
                parent = grandparent
                temp_parent = k
                print ("parent >>>>> ",parent)

                if isinstance(v, (dict, list)):
                    parent = temp_parent
                    print ("IF VALUE DICT .. parent ", parent)
                    extract(v, arr,parent)
                else:
                    grandparent = parent
                    parent = parent + "_" + temp_parent
                    print ("!!!!   NOT DICT :).... **** parent  ... ", parent)
                    arr.append(parent)

        elif isinstance(obj, list):
            for item in obj:
                extract(item, arr)
        #print ("arr >>>>>>>>>> ", arr)
        time.sleep(5)
        return arr

    results = extract(obj, arr,parent)
    return results

Но это не дает ожидаемого результата. Ожидаемый результат:

keyList= ["Name1.NNum","Name1.Node1.SubNodeA",""Name1.Node1.SubNodeB","Name1.Node2.SubNodeA","Name1.Node2.SubNodeD","Name1.Node2.SubNodeE","Name1.Node3.child1","Name1.Node3.child2.grandchild.greatgrandchild1","Name1.Node3.child2.grandchild.greatgrandchild2"]

Кто-нибудь может мне помочь с этим. заранее спасибо

1
AIMCognitiveGurgaon BigData 8 Июл 2019 в 10:53

5 ответов

Лучший ответ
def getKeys(object, prev_key = None, keys = []):
    if type(object) != type({}):
        keys.append(prev_key)
        return keys
    new_keys = []
    for k, v in object.items():
        if prev_key != None:
            new_key = "{}.{}".format(prev_key, k)
        else:
            new_key = k
        new_keys.extend(getKeys(v, new_key, []))
    return new_keys

Это решение предполагает, что внутренние типы, которые могут иметь потомков, являются словарями.

1
Tom Ron 8 Июл 2019 в 08:05

Вы можете использовать рекурсию:

d = {'Name1': {'NNum': '11', 'Node1': {'SubNodeA': 'Thomas', 'SubNodeB': '27'}, 'Node2': {'SubNodeA': 'ZZZ', 'SubNodeD': 'XXX', 'SubNodeE': 'yy'}, 'Node3': {'child1': 11, 'child2': {'grandchild': {'greatgrandchild1': 'Rita', 'greatgrandchild2': 'US'}}}}}
def keys(d, c = []):
  return [i for a, b in d.items() for i in ([c+[a]] if not isinstance(b, dict) else keys(b, c+[a]))]

result = list(map('.'.join, keys(d)))

Выход:

['Name1.NNum', 'Name1.Node1.SubNodeA', 'Name1.Node1.SubNodeB', 'Name1.Node2.SubNodeA', 'Name1.Node2.SubNodeD', 'Name1.Node2.SubNodeE', 'Name1.Node3.child1', 'Name1.Node3.child2.grandchild.greatgrandchild1', 'Name1.Node3.child2.grandchild.greatgrandchild2']
0
Ajax1234 8 Июл 2019 в 15:31

Используйте isinstance для проверки dict or not, вызываемого функцией рекурсивно. Если dict добавить к path рекурсивно, иначе выведите path

def print_nested_keys(dic,path=''):
    for k,v in dic.items():
        if isinstance(v,dict):
            path+=k+"."
            yield from print_nested_keys(v,path)
        else:
            path+=k
            yield path

< Сильный > Вывод :

>>> [*print_nested_keys(d)] # Here, d is your nested dictionary
['Name1.NNum',
 'Name1.NNumNode1.SubNodeA',
 'Name1.NNumNode1.SubNodeASubNodeB',
 'Name1.NNumNode1.Node2.SubNodeA',
 'Name1.NNumNode1.Node2.SubNodeASubNodeD',
 'Name1.NNumNode1.Node2.SubNodeASubNodeDSubNodeE',
 'Name1.NNumNode1.Node2.Node3.child1',
 'Name1.NNumNode1.Node2.Node3.child1child2.grandchild.greatgrandchild1',
 'Name1.NNumNode1.Node2.Node3.child1child2.grandchild.greatgrandchild1greatgrandchild2']
1
shaik moeed 8 Июл 2019 в 08:52

Вы можете сделать простую рекурсию:

d = {
    "Name1": {
        "NNum": "11",
        "Node1": {
            "SubNodeA": "Thomas",
            "SubNodeB": "27"
        },
        "Node2": {
            "SubNodeA": "ZZZ",
            "SubNodeD": "XXX",
            "SubNodeE": "yy"
        },
        "Node3": {
                "child1": 11,
                "child2": {
                    "grandchild": {
                        "greatgrandchild1": "Rita",
                        "greatgrandchild2": "US"
                                }
                            }
                }
            }
}

def get_keys(d, curr_key=[]):
    for k, v in d.items():
        if isinstance(v, dict):
            yield from get_keys(v, curr_key + [k])
        elif isinstance(v, list):
            for i in v:
                yield from get_keys(i, curr_key + [k])
        else:
            yield '.'.join(curr_key + [k])

print([*get_keys(d)])

Печать :

['Name1.NNum', 'Name1.Node1.SubNodeA', 'Name1.Node1.SubNodeB', 'Name1.Node2.SubNodeA', 'Name1.Node2.SubNodeD', 'Name1.Node2.SubNodeE', 'Name1.Node3.child1', 'Name1.Node3.child2.grandchild.greatgrandchild1', 'Name1.Node3.child2.grandchild.greatgrandchild2']
1
Andrej Kesely 8 Июл 2019 в 08:24

Как насчет этого?

from collections import Mapping

def extract_paths(base_path, dd): 
    new_paths = [] 
    for key, value in dd.items(): 
        new_path = base_path + ('.' if base_path else '') + key 
        if isinstance(value, Mapping): 
            new_paths.extend(extract_paths(new_path, value)) 
        else: 
            new_paths.append(new_path) 
    return new_paths

extract_paths('', your_dict)
1
josoler 8 Июл 2019 в 08:10