В главе Внешние API уже описано как начать работать с JSON. Так вот пора оседлать эту лошадку 🐎!
Иногда в одной строке удобно хранить несколько переменных. Как в сумочке может уместиться одновременно множество вещей.
Допустим, 7 августа 2018 года в 22:36 Мария Ивановна решила признаться в любви юноше по имени JSON.
Время необходимо перевести в формат UNIX. Это делается для того, чтобы было удобно проводить вычисления, например, отнимать одну дату от другой. Здесь можно перевести время в формат UNIX и обратно. В нашем примере 7 августа 2018 года 22:36 будет ни что иное как 1533670582.
Запишем этот факт в переменную %X в виде JSON строки:
%X={"Name":"Мария Ивановна","Message":"I ❤️ JSON","Time":1533670582}
Если расшифровать содержание переменной X, окажется, что:
Name="Мария Ивановна"
Message="I ❤️ JSON"
Time=1533675776
Отформатированная строка JSON выглядит так:
🐫 Обратите внимание, что тексты берутся в кавычки, а числа нет.
Вроде понятно! Осталось научить этому бота.
Разберём как выглядит узел для работы с JSON:
$.jsonPath %variable method(),
где jsonPath
— путь к переменной внутри JSON (можно опустить при работе с корневым элементом);
%variable
— переменная содержащая строку JSON;
method()
— имя метода (не используется в режиме чтения).
Как мы помним в переменной X лежит строка JSON {"Name":"Мария Ивановна","Message":"I ❤️ JSON","Time":1533670582} или:
Прочтем Message из нашей JSON-строки:
%Y=$.Message %X
Теперь %Y содержит сообщение “I ❤️ JSON”.
Ура!
А сейчас немного усложним задачу. Представим, что наша Мария Ивановна, которой 31 год, решила пойти в гастроном. Для этого она написала список продуктов, разделив их по группам: фрукты, овощи, мясо.
Попробуем узнать что у Марии Ивановны первое в списке продуктов из мясного отдела. Для этого нам нужно указать путь к месту в JSON-строке с нужной переменной.
Этот путь выглядит так: grocery[2].variety[0].
А это весь узел, который положит значение в нужную переменную %Y:
%Y=$.grocery[2].variety[0] %X
Как же узнать путь до нужного значения? В нашем случае JSON содержит переменные на нескольких уровнях. На первом уровне name, age, gender и grocery. Нас интересует переменная grocery, ведь в ней содержится список покупок. Идем в мясную категорию. Хотя в списке она третья, но имеет номер 2, потому что нумерация в JSON начинается с нуля, а не с единицы. Таким образом grocery[2] означает, что мы находимся в мясном отделе. Остается выбрать первый продукт в списке. Как мы теперь знаем, его порядковый номер 0, соответственно нам нужна variety[0]. Таким образом путь grocery[2].variety[0] укажет нам на нужное значение, а узел %Y=$.grocery[2].variety[0] %X
положит в %Y значение Pork.
Вот и всё!
🐫 Проверить путь к нужной переменной JSON можно тут http://jsonpath.com
А вдруг мы понятия не имеем на каком месте в списке Марии Ивановны находятся мясные продукты? Тогда просто найдем их по имени
%Y=$.grocery[?(@.name=="Meat")].variety[0] %X
Для этого в пути укажем имя раздела Meat и возьмем первое значение. Получится свинина! 🐷
Мало того мы можем получать целые куски JSON. Например, если нам нужен перечень всех мясных продуктов из списка Марии Ивановны, сделаем это так:
%Y=$.grocery[?(@.name=="Meat")]
Таким образом, %Y тоже станет JSON-строкой со следующим содержанием:
Как добавить данные в существующий JSON? Наш JSON находится в переменной %X. Добавим в список Марии Ивановны сыр. Для этого запишем в %Z перечень сыров:
%Z={"name":"Cheese","variety":["Cheddar","Mozzarella","Feta"]}
А теперь добавим все это в %X:
$.grocery %X add(%Z)
Получим такой вот JSON:
Давайте удалим мясо из списка покупок:
$.grocery %X remove({"name":"Meat"})
Также можно удалить данные с помощью jsonPath
$.grocery[?(@.name=="Meat")] %X remove()
Теперь Мария Ивановна еще и вегетарианка.
Например последний добавленный сыр:
%Y=$.grocery[?(@.name=="Cheese")].variety %X pop()
%Y будет содержать Feta. В тоже время из JSON этот элемент будет удален.
Теперь самая интересная штука.
JSON содержит наборы одинаковых элементов, например перечень фруктов. Вывести все элементы из списка фруктов поможет конструкция:
$.grocery[?(@.name=="Fruits")].variety %X each(%item)
Берем JSON %X, указываем путь к фруктам $.grocery[?(@.name=="Fruits")].variety и кладем по очереди фрукты в %item.
Осталось из этого узла сделать две ветки:
Заработало!
Примеры последовательно показаны в карте:
Click icon to copy this map or open it in