К сожалению, 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.
- pick — столбец с (неудивительно) элементами pick,
- elements - столбец с элементами (пока что каждая ячейка содержит весь список).
Эта фигура не очень полезна, поэтому давайте расчленим столбец elements:
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
А для получения конечного результата следует:
- выберите строки со столбцом pick == id,
- взять только столбец elements (вместе с ключевым столбцом, но эту деталь Pandas дает вам прямо из коробки).
Код для этого:
df.query('pick == id').elements
давая:
x1 {'id': 'a', 'label': 'First_a'}
x2 {'id': 'b', 'label': 'Second_b'}
На языке Pandas это серия (скажем, список, в котором каждый элемент «помечен» индексом.
Теперь вы можете преобразовать его в словарь или что угодно.
person
Valdi_Bo
schedule
26.04.2020