Обновить значения в JSON используя JSONPath

Имеется JSON вида

json_example = {"a": 1, "b": {"c": 2, "d": {"e": 3}}}

Хочу написать функцию по обновлению значения по произвольному пути:

some_func(json_example, "a.b.c", 0)
# {"a": 1, "b": {"c": 0, "d": {"e": 3}}}

или:

some_func(json_example, "a.b.c.d.e", 0)
# {"a": 1, "b": {"c": 2, "d": {"e": 0}}}

С получением значения разобрался, но по такой же аналогии запись не сделать из-за постепенной потерии исходного JSON.

for sub_path in path.split(".")[:-1]:
    json_example = json_example.setdefault(sub_path, {})
json_example[json_path.split(".")[-1]]

Пытался нагуглить какую-то библиотеку для работы с JSONPath, но они все для запросов на чтение. Можно ли как-то реализовать запись по пути?


Ответы (2 шт):

Автор решения: hedgehogues

Вы стали решать довольно сложную задачу. К сожалению, алгоритм нетривиален. Я думаю, что Вам следует посмотреть уже на готовое решение, которое выражается в утилите jq. Я не слышал о том, чтобы jq умел бы обновлять данные. Но, возможно, и умеет. Я основываюсь на этом вопросе. Если jq не поддерживает такой функционал, тогда посмотрите исходники утилиты. Скорее всего Вы поймёте, как решить Вашу задачу.

→ Ссылка
Автор решения: MaxU

Воспользуйтесь готовым модулем dpath для работы со словарями любой вложенности.

JSON можно легко прочитать в словарь и дальше работать со словарем.

Пример:

import dpath.util as dp   #  pip install dpath

In [31]: dp.set(json_example, 'b/d/e', 111)
Out[31]: 1

In [32]: json_example
Out[32]: {'a': 1, 'b': {'c': 2, 'd': {'e': 111}}}

In [33]: dp.set(json_example, '[ab]/[cd]/e', 222)
Out[33]: 1

In [34]: json_example
Out[34]: {'a': 1, 'b': {'c': 2, 'd': {'e': 222}}}

In [35]: dp.set(json_example, '**/e', 333)
Out[35]: 1

In [36]: json_example
Out[36]: {'a': 1, 'b': {'c': 2, 'd': {'e': 333}}}
→ Ссылка