Использование REST API с curl и jq
Объединяйте запросы curl с jq, чтобы извлекать, разбивать на страницы и преобразовывать актуальные ответы API в скриптах
«Использование REST API с curl и jq» — бесплатный урок Linux Command Line & Bash Scripting Mastery на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Linux Command Line & Bash Scripting Mastery, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Linux Command Line & Bash Scripting Mastery содержит 4 уроков всего.
Почему curl + jq — мощная комбинация
REST API возвращают JSON. curl получает необработанный ответ, а jq извлекает, фильтрует и изменяет его структуру — всё в одном конвейере. Не нужны ни скрипт Python, ни Postman, ни промежуточный файл.
- curl работает с HTTP: методами, заголовками, аутентификацией и перенаправлениями.
- jq работает с JSON: фильтрацией, отображением, преобразованием и форматированием.
- Объединение этих инструментов через конвейер создаёт лаконичные и комбинируемые процессы работы с API.
В этом уроке навык формируется с основ, включая реальные шаблоны постраничной выдачи и написания скриптов.
Базовый конвейер curl с передачей в jq
Самый простой шаблон: передать вывод curl непосредственно в jq. Используйте -s (без вывода) в curl, чтобы скрыть индикатор выполнения и передать в jq только тело JSON.
-s— тихий режим без индикатора выполнения..— фильтр идентичности jq; выводит полный ответ в удобном для чтения формате.-rв jq — необработанный вывод (для строк без окружающих кавычек).
#!/usr/bin/env bash
# Fetch a public endpoint and pretty-print the JSON
curl -s 'https://jsonplaceholder.typicode.com/todos/1' | jq '.'
# Extract just the title field as a plain string
curl -s 'https://jsonplaceholder.typicode.com/todos/1' | jq -r '.title'Настройка заголовков запроса и передача токенов аутентификации
Большинство рабочих API требуют заголовок Authorization или ключ API. Передавайте заголовки с помощью -H, а секреты храните в переменных окружения — никогда не встраивайте их непосредственно в код.
-H 'Authorization: Bearer $TOKEN'— добавляет заголовок аутентификации.-H 'Accept: application/json'— явно запрашивает ответ в формате JSON.- Переменные раскрываются внутри двойных кавычек; используйте
"вокруг строки заголовка.
#!/usr/bin/env bash
TOKEN="${GITHUB_TOKEN}" # set in your shell environment
USER="octocat"
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/users/${USER}" \
| jq '{login: .login, repos: .public_repos, followers: .followers}'Фильтрация массивов — .[] и select()
API часто возвращают массивы. Используйте .[], чтобы перебрать каждый элемент, а затем select(), чтобы оставить только элементы, соответствующие условию.
.[]— раскрывает массив в поток объектов.select(.field == value)— оставляет только подходящие объекты.- Объединяйте несколько фильтров с помощью
|.
#!/usr/bin/env bash
# Fetch all todos and keep only the completed ones
curl -s 'https://jsonplaceholder.typicode.com/todos' \
| jq '[.[] | select(.completed == true) | {id, title}]'
# Count how many are completed
curl -s 'https://jsonplaceholder.typicode.com/todos' \
| jq '[.[] | select(.completed == true)] | length'Извлечение нескольких полей с помощью map()
map() применяет преобразование к каждому элементу массива и возвращает новый массив — это эквивалент [.[] | ...], но в более удобной для чтения форме.
map({key: .field})— изменяет структуру каждого объекта.- Объединяйте с
@csvили@tsv, чтобы получить табличный вывод. - Используйте
-rвместе с@csv/@tsv, чтобы получить необработанный текст (без экранирования в формате JSON).
#!/usr/bin/env bash
# Reshape a posts list into id + title pairs
curl -s 'https://jsonplaceholder.typicode.com/posts' \
| jq 'map({id, title: .title[0:40]})'
# Output as CSV for import into a spreadsheet
curl -s 'https://jsonplaceholder.typicode.com/posts' \
| jq -r '.[] | [.id, .userId, .title] | @csv'Шаблон разбиения на страницы — цикл до пустой страницы
Большинство API разбивают результаты на страницы. Распространённый шаблон — цикл while, который увеличивает счётчик страниц и останавливается, когда возвращённый массив оказывается пустым.
- Сохраните ответ curl в переменную с помощью
$(curl ...). - Используйте
jq 'length', чтобы проверить, есть ли на странице элементы. - Накапливайте результаты с помощью
jq -s(объединение в один массив) или добавляйте их в файл.
#!/usr/bin/env bash
# Paginate through jsonplaceholder posts (simulated: page stops at page 2
# because the API returns the full list regardless of ?_page, but the
# pattern is correct for real paginated APIs)
PAGE=1
PER_PAGE=10
OUTPUT="all_posts.json"
echo '[]' > "$OUTPUT"
while true; do
RESPONSE=$(curl -s "https://jsonplaceholder.typicode.com/posts?_page=${PAGE}&_limit=${PER_PAGE}")
COUNT=$(echo "$RESPONSE" | jq 'length')
if [ "$COUNT" -eq 0 ]; then
echo "No more pages. Stopping at page $((PAGE - 1))."
break
fi
# Merge new items into the accumulated JSON array
CURRENT=$(cat "$OUTPUT")
echo "$CURRENT" "$RESPONSE" | jq -s '.[0] + .[1]' > "$OUTPUT"
echo "Page $PAGE: fetched $COUNT items."
PAGE=$((PAGE + 1))
done
echo "Total collected: $(jq 'length' "$OUTPUT")"Разбиение на страницы по заголовку Link (стиль GitHub)
GitHub и многие другие API используют заголовок ответа Link, чтобы передать URL следующей страницы. Необходимо разобрать этот заголовок, а не угадывать URL.
curl -iвключает заголовки ответа в stdout; также можно использовать-D -, чтобы вывести заголовки в stdout.- Разберите заголовок
Link: <url>; rel="next"с помощьюgrepиsed. - Выполняйте цикл, пока не исчезнет ссылка с
rel="next".
#!/usr/bin/env bash
# Follow Link-header pagination (GitHub repos example)
# Requires GITHUB_TOKEN in environment
TOKEN="${GITHUB_TOKEN}"
NEXT_URL="https://api.github.com/users/torvalds/repos?per_page=5"
ALL_REPOS="[]"
while [ -n "$NEXT_URL" ]; do
# Capture full response (headers + body) to a temp file
TMPFILE=$(mktemp)
curl -sD "$TMPFILE" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: application/vnd.github+json" \
"$NEXT_URL" \
| {
BODY=$(cat)
ALL_REPOS=$(echo "$ALL_REPOS" "$BODY" | jq -s '.[0] + .[1]')
echo "$ALL_REPOS" > /tmp/repos_acc.json
}
# Extract next URL from Link header
NEXT_URL=$(grep -i '^link:' "$TMPFILE" \
| sed -E 's/.*<([^>]+)>; rel="next".*/\1/;t;d')
rm -f "$TMPFILE"
done
echo "Total repos: $(jq 'length' /tmp/repos_acc.json)"Цепочка запросов — использование вывода одного вызова как входных данных для другого
Распространённый рабочий процесс: получить список, извлечь ID, а затем получить подробные данные для каждого ID. Сохраняйте промежуточные значения с помощью подстановки команд $() и передавайте их в следующий URL.
- Извлеките одно значение с помощью
jq -r '.field'. - Перебирайте несколько ID с помощью
jq -r '.[].id'внутри циклаwhile read. - Используйте
sleepмежду запросами, чтобы соблюдать ограничения частоты запросов.
#!/usr/bin/env bash
# Step 1: get all user IDs from the /users endpoint
# Step 2: for each user, fetch their posts and count them
curl -s 'https://jsonplaceholder.typicode.com/users' \
| jq -r '.[].id' \
| while read -r USER_ID; do
POST_COUNT=$(curl -s "https://jsonplaceholder.typicode.com/posts?userId=${USER_ID}" \
| jq 'length')
echo "User ${USER_ID}: ${POST_COUNT} posts"
sleep 0.1 # be polite to the API
doneЗапросы POST — отправка полезной нагрузки JSON
Чтобы создать или обновить ресурсы, отправьте POST или PUT с телом в формате JSON. Используйте -X POST, -H 'Content-Type: application/json' и -d для передачи тела. Формируйте полезную нагрузку с помощью jq -n, чтобы избежать проблем с экранированием кавычек.
jq -n --arg key value '{key: $key}'— безопасная подстановка переменных в jq.- Передавайте сформированный JSON напрямую в
-d @-команды curl (тело считывается из стандартного ввода). - Сразу разбирайте ответ с помощью другого фильтра jq.
#!/usr/bin/env bash
TITLE="My New Post"
BODY_TEXT="Written via curl and jq."
USER_ID=1
# Build the JSON payload safely and POST it
RESPONSE=$(jq -n \
--arg title "$TITLE" \
--arg body "$BODY_TEXT" \
--argjson userId "$USER_ID" \
'{title: $title, body: $body, userId: $userId}' \
| curl -s \
-X POST \
-H 'Content-Type: application/json' \
-d @- \
'https://jsonplaceholder.typicode.com/posts')
echo "Created post ID: $(echo "$RESPONSE" | jq '.id')"
echo "Full response:"
echo "$RESPONSE" | jq '.'Обработка ошибок — коды состояния HTTP и ошибки API
Успешное HTTP-соединение не означает, что вызов API выполнен успешно. Отдельно проверьте код состояния HTTP и поле ошибки в JSON.
curl -w '%{http_code}'добавляет код состояния в stdout; используйте-o, чтобы записать тело ответа в файл.- Сравните код в скрипте и обрабатывайте ответы 4xx и 5xx по-разному.
- Многие API встраивают в тело ответ вида
{"error": "..."}— проверьте его с помощьюhas()илиtypeиз jq.
#!/usr/bin/env bash
API_URL='https://jsonplaceholder.typicode.com/todos/99999'
TMPBODY=$(mktemp)
HTTP_CODE=$(curl -s -o "$TMPBODY" -w '%{http_code}' "$API_URL")
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
echo "Success ($HTTP_CODE):"
jq '.' "$TMPBODY"
elif [ "$HTTP_CODE" -eq 404 ]; then
echo "Resource not found (404). Body:"
jq '.' "$TMPBODY"
elif [ "$HTTP_CODE" -ge 500 ]; then
echo "Server error ($HTTP_CODE). Retrying later."
else
echo "Unexpected status: $HTTP_CODE"
cat "$TMPBODY"
fi
rm -f "$TMPBODY"Создание повторно используемой вспомогательной функции для API
Оберните стандартный код для curl и проверки ошибок в функцию оболочки. Функция обрабатывает аутентификацию, проверку состояния и извлечение данных из JSON — вызывающему коду достаточно передать конечную точку и фильтр jq.
- Возвращайте ненулевые коды завершения при ошибках HTTP, чтобы вызывающий код мог использовать
||илиset -e. - Принимайте фильтр jq как аргумент, чтобы одна и та же функция работала с разными конечными точками.
- Подключайте файл с этой функцией из любого скрипта, которому нужен API.
#!/usr/bin/env bash
# api_get <endpoint_path> <jq_filter>
# Returns filtered JSON or exits non-zero on error.
api_get() {
local PATH_PART="$1"
local JQ_FILTER="${2:-.}"
local BASE_URL='https://jsonplaceholder.typicode.com'
local TMPBODY
TMPBODY=$(mktemp)
local HTTP_CODE
HTTP_CODE=$(curl -s \
-o "$TMPBODY" \
-w '%{http_code}' \
"${BASE_URL}${PATH_PART}")
if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 300 ]; then
echo "[ERROR] HTTP $HTTP_CODE for ${PATH_PART}" >&2
rm -f "$TMPBODY"
return 1
fi
jq -r "$JQ_FILTER" "$TMPBODY"
rm -f "$TMPBODY"
}
# Usage examples
api_get '/todos/1' '.title'
api_get '/posts?userId=1' '[.[] | .title]'
api_get '/users' '.[] | "\(.id) \(.name) <\(.email)>"'Проверка знаний: стратегия разбиения на страницы
Проверьте, насколько хорошо Вы умеете обрабатывать ответы REST API, разбитые на страницы, в скрипте Bash с использованием curl и jq.
Итоги урока: написание скриптов для API с curl и jq
Теперь у Вас есть полный набор инструментов для работы с REST API из командной строки Bash:
- Базовый конвейер:
curl -s URL | jq 'filter'— основа всего остального. - Заголовки аутентификации: передавайте токены через
-Hиз переменных окружения, никогда не встраивайте их непосредственно в код. - Работа с массивами:
.[],select()иmap()извлекают части ответа API и изменяют его структуру. - Разбиение на страницы: выполняйте цикл со счётчиком страниц (признаком окончания служит пустой массив) или разбирайте заголовки
Linkв API, использующих URL следующей страницы. - Цепочка запросов: извлекайте ID из одного ответа и передавайте их в следующий запрос внутри цикла
while read. - POST с безопасной полезной нагрузкой: формируйте тела JSON с помощью
jq -n --argи передавайте их через-d @-команды curl. - Обработка ошибок: отделяйте состояние HTTP (
-w '%{http_code}') от ошибок уровня API в теле ответа. - Повторно используемая вспомогательная функция: выносите стандартный код в функцию оболочки, чтобы скрипты оставались краткими и соответствовали принципу DRY.
Объединяя эти шаблоны, Вы сможете полностью автоматизировать работу с любым API JSON из оболочки — дополнительная среда выполнения не требуется.
Часто задаваемые вопросы
Урок «Использование REST API с curl и jq» бесплатный?
Да — полный текст урока «Использование REST API с curl и jq» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Linux Command Line & Bash Scripting Mastery, подпишись на CoddyKit PRO. Курс Linux Command Line & Bash Scripting Mastery содержит 4 уроков всего.
Чему я научусь в уроке «Использование REST API с curl и jq»?
Объединяйте запросы curl с jq, чтобы извлекать, разбивать на страницы и преобразовывать актуальные ответы API в скриптах Ты практикуешь Linux Command Line & Bash Scripting Mastery с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Linux Command Line & Bash Scripting Mastery?
Предыдущий опыт не требуется. Linux Command Line & Bash Scripting Mastery на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Использование REST API с curl и jq»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Linux Command Line & Bash Scripting Mastery?
Да. Каждый урок Linux Command Line & Bash Scripting Mastery включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Фильтрация и выборка JSON с конвейерами jq
- Преобразование и создание объектов JSON с jq
- Использование REST API с curl и jq
- Редактирование файлов конфигурации YAML с yq