Обновить значения в 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 шт):
Вы стали решать довольно сложную задачу. К сожалению, алгоритм нетривиален. Я думаю, что Вам следует посмотреть уже на готовое решение, которое выражается в утилите jq. Я не слышал о том, чтобы jq умел бы обновлять данные. Но, возможно, и умеет. Я основываюсь на этом вопросе. Если jq не поддерживает такой функционал, тогда посмотрите исходники утилиты. Скорее всего Вы поймёте, как решить Вашу задачу.
Воспользуйтесь готовым модулем 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}}}