0Pricing
Linux Command Line & Bash Scripting Mastery · Урок

Использование 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 — локальная установка не требуется.

Все уроки этого курса

  1. Фильтрация и выборка JSON с конвейерами jq
  2. Преобразование и создание объектов JSON с jq
  3. Использование REST API с curl и jq
  4. Редактирование файлов конфигурации YAML с yq
← Назад к Linux Command Line & Bash Scripting Mastery