Функции, которые помогают понять структуру json (dict)

Я не нашел, есть ли способ сделать это. Скажем, я получаю объект JSON следующим образом:

{'1_data':{'4_data':[{'5_data':'hooray'}, {'3_data':'hooray2'}], '2_data':[]}} 

Трудно сразу сказать, как мне получить значение из ключа 3_data : data['1_data']['4_data'][1]['3_data']

Я знаю о pprint , это помогает понять структуру немного. Но иногда данные огромны, и требуется время

Существуют ли какие-либо методы, которые могут мне помочь?

Вот семейство рекурсивных генераторов, которые можно использовать для поиска объекта, состоящего из диктонов и списков. find_key дает кортеж, содержащий список ключей словаря и индексов списков, которые приводят к ключу, который вы передаете; кортеж также содержит значение, связанное с этим ключом. Поскольку это генератор, он найдет все соответствующие ключи, если объект содержит несколько подходящих ключей, если это необходимо.

 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]) # test data = { '1_data': { '4_data': [ {'5_data': 'hooray'}, {'3_data': 'hooray2'} ], '2_data': [] } } for t in find_key(data, '3_data'): print(t) 

вывод

 (['1_data', '4_data', 1, '3_data'], 'hooray2') 

Чтобы получить один список ключей, вы можете передать find_key next функции. И если вы хотите использовать список ключей для извлечения связанного значения, вы можете использовать простой цикл.

 seq, val = next(find_key(data, '3_data')) print('seq:', seq, 'val:', val) obj = data for k in seq: obj = obj[k] print('obj:', obj, obj == val) 

вывод

 seq: ['1_data', '4_data', 1, '3_data'] val: hooray2 obj: hooray2 True 

Если ключ может отсутствовать, введите next соответствующий кортеж по умолчанию. Например:

 seq, val = next(find_key(data, '6_data'), ([], None)) print('seq:', seq, 'val:', val) if seq: obj = data for k in seq: obj = obj[k] print('obj:', obj, obj == val) 

вывод

 seq: [] val: None 

Обратите внимание, что этот код предназначен для Python 3. Чтобы запустить его на Python 2, вам нужно заменить весь yield from операторов, например, заменить

 yield from iter_dict(obj, key, []) 

с

 for u in iter_dict(obj, key, []): yield u 

Как это работает

Чтобы понять, как работает этот код, вам нужно быть знакомым с рекурсией и с генераторами Python. Вы также можете найти эту страницу полезной: Общие сведения о генераторах в Python ; существуют также различные обучающие программы для генераторов Python, доступные в Интернете.

Объект Python, возвращаемый json.load или json.loads , обычно является dict, но также может быть списком. Мы передаем этот объект генератору find_key в качестве obj arg вместе с key строкой, которую мы хотим найти. find_key затем вызывает либо iter_dict либо iter_list , когда это необходимо, передавая им объект, ключ и пустые indices списка, которые используются для сбора ключей dict и индексов списка, которые приводят к желаемому ключу.

iter_dict выполняет iter_dict по каждой (k, v) паре на верхнем уровне своего d dict arg. Если k совпадает с ключом, который мы ищем, то текущий список indices будет получен с добавленным к нему k вместе с соответствующим значением. Поскольку iter_dict рекурсивно, полученные пары (индексы списка, значения) передаются до предыдущего уровня рекурсии, в конечном итоге find_key к find_key а затем в код, который называется find_key . Обратите внимание, что это «базовый случай» нашей рекурсии: это часть кода, которая определяет, ведет ли этот путь рекурсии к нужному ключу. Если путь рекурсии никогда не находит ключ, соответствующий ключевому слову, который мы ищем, то этот путь рекурсии ничего не добавит к indices и он завершится без каких-либо изменений.

Если текущий v является dict, тогда нам нужно изучить все пары (ключ, значение), которые он содержит. Мы делаем это, рекурсивным вызовом iter_dict , передавая, что v является его стартовым объектом и текущим списком indices . Если текущий v является списком, мы вместо этого называем iter_list , передавая ему те же аргументы.

iter_list работает так же, как и iter_dict за исключением того, что в списке нет ключей, он содержит только значения, поэтому мы не выполняем k == key тест k == key , мы просто рекурсируем в любые dicts или списки, которые содержит исходный список.

Конечным результатом этого процесса является то, что при find_key по find_key мы получаем пары (индексы, значение), где каждый список indices представляет собой последовательность ключей dict и индексов списка, которые успешно завершаются в элементе dict с помощью нашего желаемого ключа, а value равно значение, связанное с этим конкретным ключом.

Если вы хотите увидеть некоторые другие примеры использования этого кода, посмотрите, как изменить ключ вложенного Json и как я могу выбрать глубоко вложенный ключ: значения из словаря в python .

  • Каково формальное различие между «печатью» и «возвратом»?
  • Как конвертировать секунды в часы, минуты и секунды?
  • Почему некоторые встроенные функции Python имеют пропуск?
  • Как использовать инструкцию pass?
  • В чем цель __str__ и __repr__?
  • Как ускорить массовую вставку в MS SQL Server из CSV, используя pyodbc
  • Разбор комбинации обратного слэша и косой черты в имени файла
  • Как определить, является ли переменная Python функцией?
  • Как создавать списки содержат только отдельный элемент в Python?
  • Как точно работает понимание генератора?
  • Декодер classа classа Python с собственными аргументами?
  • Давайте будем гением компьютера.