8 секретных приёмов jq, после которых вы забудете про мучения с JSON!

Мужчина с ноутбуком на фоне надписи .JSON, фигурных скобок и фрагментов кода.

Эти фильтры jq становятся настоящей палочкой-выручалочкой на каждый день: фильтрация, преобразование, сжатие, сортировка, подстановка дефолтных значений и красивое форматирование. На примерах я покажу, как всё это работает и почему с ними вы справитесь с любыми данными.

Как быстро найти нужные объекты по свойству

Задача похожа на работу с базой данных: jq отлично справляется с поиском объектов с определённым значением свойства. Для этого есть функция select:

Допустим, у вас массив объектов и нужно вытащить среди них только определённые. Они останутся внутри массива. Например, возьмём такую структуру:

Чтобы получить элемент с нужным значением, используйте такой фильтр:

Фильтр jq select возвращает объект, соответствующий условию.

Переводим строку в формат URI одной командой

В jq есть фильтры, начинающиеся с @ — они предназначены для правильного кодирования и преобразования строк. С их помощью можно получить данные для CSV, HTML, base64 или для использования в URI:

Этот фильтр берет специальные символы и превращает их в %XX-кодировку (например, двоеточие, @, вопросительный знак и другие).

Чтобы применить фильтр, просто подайте ему строку, например так:

В ответ вы получите строку, где все «опасные» символы заменены на безопасные коды:

Фильтр jq @uri превращает специальные символы в закодированные формы.

Обратите внимание: этот фильтр нужен для отдельных значений — например, фрагментов адреса или параметров, но не для целого URL.

Как преобразовать структуру объекта за пару строк

Порой нужно поменять саму структуру данных в JSON — и тут фильтр map приходит на помощь. Он применяет функцию к каждому элементу массива или объекту. Это универсальный инструмент для любых преобразований.

Пример исходных данных:

Допустим, вы хотите получить итоговую структуру вот так:

Сначала придумайте, как должно выглядеть новое представление информации:

А потом используйте map, чтобы вытащить нужные поля из оригинальных объектов:

Получаем одно значение из целого массива

Операция reduce — настоящая классика: когда нужно просуммировать весь массив или собрать всё в одну строку. В jq это делается вот так:

В init вы задаёте начальное значение, а обновление результата происходит через update. Например, чтобы найти сумму всех чисел:

Или склеить все строки вместе:

Как вытащить число из текста

Часто попадаются «грязные» данные: числа спрятаны прямо в тексте, а работать нужно именно с цифрами. Проблему решает функция match: она ищет по регулярному выражению и возвращает детали — смещение (offset), длину (length) и само найденное значение:

Фильтр jq match возвращает объект с подробностями совпадения: offset, длина, значение.

Чтобы получить только само число, просто возьмите свойство string из этого объекта:

Гибкое форматирование дат и времени

В jq есть простые способы работать с датой и временем. Как и во многих языках, здесь доступна функция strftime (её знают все, кто писал на C). Ещё есть функция now, чтобы получить текущее время в секундах с 1970 года:

Фильтр jq now возвращает число секунд с 1 января 1970 года.

В strftime можно задать любой формат вашей ОС: %Y — год, %s — секунды с эпохи Unix, %A — полное название дня недели, %+ — быстрое представление даты и времени:

Фильтр jq strftime с %+ показывает дату, время, день недели и часовой пояс.

Подставляем значения по умолчанию, если данных не хватает

Когда вы создаёте объект из исходных данных, иногда надо подставить «запасные» значения, если что-то отсутствует. Например, такие данные:

Обычно это решается просто: конструкция if-then-else справляется отлично. Если нужный параметр найден — объект не меняется, если его нет — добавляете свойство с нужным дефолтом через оператор +:

Такой приём гарантирует, что во всех объектах будут необходимые параметры и корректные значения по умолчанию:

Фильтр с условием подставляет значения для отсутствующих свойств объекта.

Как реально объединять объекты целиком

В предыдущем примере оператор + соединял два объекта — этого хватает для простых задач:

Ключ -n даёт jq знать, что он работает с пустым вводом — удобно для тестов.

Но если ваши объекты сложные и многослойные, оператор + уже не спасёт: он соединит только то, что лежит на поверхности («shallow merge»). Например, этот фильтр не даст глубокого объединения:

В результате вы получите только «верхушку айсберга»:

Для полноценного, глубокого слияния используйте оператор * — он объединяет объекты на всех уровнях вложенности:

Фильтр jq с оператором * выполняет глубокое объединение объектов.

Если вам понравилась эта статья, подпишитесь, чтобы не пропустить еще много полезных статей!

Премиум подписка — это доступ к эксклюзивным материалам, чтение канала без рекламы, возможность предлагать темы для статей и даже заказывать индивидуальные обзоры/исследования по своим запросам!

Подробнее о том, какие преимущества вы получите с премиум подпиской, можно узнать здесь

Также подписывайтесь на нас в:

Алекс Бежбакин
Оцените автора
Добавить комментарий