К сожалению, JMESPath не позволяет ссылаться на родительский элемент.
Чтобы обойти это ограничение, в этом простом случае вы можете:
- читать атрибут pick в первом запросе,
- создать второй запрос с использованием только что прочитанного значения,
- прочитать требуемое содержимое во втором запросе.
На самом деле, благодаря f-строкам , два последних шага могут быть выполнены в одной инструкции, поэтому код может быть:
pck = jmespath.search('pick', dct)
jmespath.search(f'elements[?id == `{pck}`]', dct)
где dct является исходным JSON объектом.
Более сложный случай
Если у вас более сложный случай (например, много таких элементов, с различными значениями pick в в каждом случае), вам следует использовать другой инструмент.
Один довольно интересный вариант - использовать пакет Pandas.
Предположим, что ваш исходный словарь содержит:
dct = {
"x1": {
"pick": "a",
"elements": [
{"id": "a", "label": "First_a"},
{"id": "b", "label": "Second_a"},
{"id": "c", "label": "Third_a"}
]
},
"x2": {
"pick": "b",
"elements": [
{"id": "a", "label": "First_b"},
{"id": "b", "label": "Second_b"},
{"id": "c", "label": "Third_b"}
]
}
}
Первое, что нужно сделать, - это преобразовать dct в Pandas DataFrame. :
import pandas as pd
df = pd.DataFrame.from_dict(dct, orient='index')
Результат (напечатанный в «сокращенной» форме):
pick elements
x1 a [{'id': 'a', 'label': 'First_a'}, {'id': 'b', ...
x2 b [{'id': 'a', 'label': 'First_b'}, {'id': 'b', ...
Описание (если у вас нет опыта в Pandas) :
- x1 , x2 , ... - столбец индекса - значения, взятые с клавиш первого уровня в dct .
- выбор - колонка с (не удивительно) выбор элементов,
- элементы - столбец с элементами (на данный момент каждая ячейка содержит весь список).
Эта форма не очень полезна, поэтому давайте взорвем элементов столбец:
df = df.explode('elements')
Теперь df содержит:
pick elements
x1 a {'id': 'a', 'label': 'First_a'}
x1 a {'id': 'b', 'label': 'Second_a'}
x1 a {'id': 'c', 'label': 'Third_a'}
x2 b {'id': 'a', 'label': 'First_b'}
x2 b {'id': 'b', 'label': 'Second_b'}
x2 b {'id': 'c', 'label': 'Third_b'}
Эта форма ближе к тому, что нам нужно: каждая исходная строка была разбита на пару строк, каждая с отделить элемент от начального списка.
Еще одна вещь, которую нужно сделать, - это создать столбец, содержащий значения id , чтобы потом сравнивать его с pick столбец. Для этого выполните:
df['id'] = df.elements.apply(lambda dct: dct['id'])
Сейчас df содержит:
pick elements id
x1 a {'id': 'a', 'label': 'First_a'} a
x1 a {'id': 'b', 'label': 'Second_a'} b
x1 a {'id': 'c', 'label': 'Third_a'} c
x2 b {'id': 'a', 'label': 'First_b'} a
x2 b {'id': 'b', 'label': 'Second_b'} b
x2 b {'id': 'c', 'label': 'Third_b'} c
И для получения окончательного результата вам необходимо:
- выберите строки с помощью выберите столбец == id ,
- возьмите только элементы столбец (вместе с ключевым столбцом, но эта деталь Pandas дает вам только что из коробки).
Код для этого:
df.query('pick == id').elements
давая:
x1 {'id': 'a', 'label': 'First_a'}
x2 {'id': 'b', 'label': 'Second_b'}
На языке Pandas это Series (скажем, список с каждым элементом, «помеченным» индексом.
Теперь вы можете преобразовать его в словарь или все, что вы будете sh.