Разбор вложенных ключей JSON - PullRequest
1 голос
/ 25 марта 2020

У меня есть файл JSON, который выглядит следующим образом:

data = {
    "x": {
        "y": {
            "key": {

            },
            "w": {

            }
}}}

И я преобразовал его в dict в python, чтобы они анализировали его для поиска ключей, используя следующий код:

entry = input("Search JSON for the following: ") //search for "key"
if entry in data:
  print(entry)
else:
  print("Not found.")

Однако, даже если я ввожу «ключ» в качестве ввода, он все равно возвращает «Не найдено». Нужно ли мне контролировать глубину данных, что если я не знаю местонахождение «ключа», но все же хочу его найти.

Ответы [ 3 ]

2 голосов
/ 25 марта 2020

Ваш метод не работает, потому что key не является ключом в data. data имеет один ключ: x. Поэтому вам нужно взглянуть на словарь и посмотреть, есть ли в нем ключ. Если нет, вы можете передать словари следующего уровня обратно в функцию рекурсивно. Он найдет первый соответствующий ключ:

data = {
    "x": {
        "y": {
            "key": "some value",
            "w": {}
}}}

key = "key"

def findValue(key, d):
    if key in d:
        return d[key]
    for v in d.values():
        if isinstance(v, dict):
            found = findValue(key, v)
            if found is not None:
                return found

findValue(key, data)  
# 'some value'

Он вернет None, если ваш ключ не найден

1 голос
/ 25 марта 2020

Вот подход, который позволяет вам собрать все значения из вложенного dict, если ключи повторяются на разных уровнях вложенности. Это очень похоже на приведенный выше ответ, просто обернут в функцию с нелокальным списком для хранения результатов:

def foo(mydict, mykey):
    result = []
    num_recursive_calls = 0

    def explore(mydict, mykey):
        #nonlocal result      #allow successive recursive calls to write to list
                              #actually this is unnecessary in this case! Here 
                              #is where we would need it, for a call counter: 
        nonlocal num_recursive_calls
        num_recursive_calls += 1
        for key in mydict.keys():   #get all keys from that level of nesting
            if mykey == key:
                print(f"Found {key}")
                result.append({key:mydict[key]})

            elif isinstance(mydict.get(key), dict):
                print(f"Found nested dict under {key}, exploring")
                explore(mydict[key], mykey)

    explore(mydict, mykey)
    print(f"explore called {num_recursive_calls} times") #see above
    return result

Например, с

data = {'x': {'y': {'key': {}, 'w': {}}}, 'key': 'duplicate'}

Это вернет:

[{'key': {}}, {'key': 'duplicate'}] 
0 голосов
/ 25 марта 2020

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

def get_key(d, k): 
  if not isinstance(d, dict): return d
  return [j for a, b in d.items() for j in [*([b] if a == k else []), *get_key(b, k)]]

data = {'x': {'y': {'key': {}, 'w': {}}}}
print(get_key(data, 'y'))
print(get_key(data, 'w'))
print(get_key(data, 'missingkey'))

Вывод:

[{'key': {}, 'w': {}}]
[{}]
[]

Результатом get_key является список, который будет содержать совпадающее значение из предоставленного ключ, если есть. Чтобы получить значение из возвращенного результата, вы можете просто проверить его достоверность: if result: #do something with result[0]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...