Работа с JSON через cURL: практическое пособие для PHP разработчиков

Раздел: Работа с JSON в PHP -> Отправка JSON через HTTP

Отправка JSON через HTTP с помощью cURL в PHP

Основной подход: использование curl_setopt с CURLOPT_POSTFIELDS и заголовком Content-Type

Для отправки JSON-данных через HTTP-запрос с помощью cURL в PHP необходимо сформировать JSON-строку, инициализировать сеанс cURL, установить необходимые опции и выполнить запрос. Ниже приведен наиболее эффективный и универсальный способ.


$data = ['name' => 'Иван', 'email' => 'ivan@example.com'];
$json = json_encode($data, JSON_UNESCAPED_UNICODE);

$ch = curl_init('https://api.example.com/users');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Content-Length: ' . strlen($json)
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode === 200) {
    $result = json_decode($response, true);
    // обработка ответа
}

Php curl application json (отправка json с помощью curl в php)

Пояснения: json_encode преобразует массив в JSON-строку. Флаг JSON_UNESCAPED_UNICODE сохраняет кириллицу без экранирования. Установка CURLOPT_POST в true указывает на POST-запрос. CURLOPT_POSTFIELDS принимает строку (не массив!) – именно так корректно отправляется JSON. Заголовок Content-Type обязателен, чтобы сервер понимал формат. Content-Length может быть опущен, но его явное указание улучшает совместимость. CURLOPT_RETURNTRANSFER возвращает ответ в переменную.

Типичные ошибки и их решение

  • Ошибка: сервер возвращает 415 Unsupported Media Type – не указан заголовок Content-Type: application/json.
  • Ошибка: curl_exec() возвращает false – необходимо проверить curl_error($ch). Частая причина: неверный URL, проблемы SSL (тогда временно можно добавить curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false) в разработке, но не в production).
  • Ошибка: сервер не принимает данные – возможно, передаётся массив в CURLOPT_POSTFIELDS (тогда PHP отправляет как form-data). Нужно обязательно передавать строку JSON.
  • Ошибка: некорректное кодирование – если не использовать JSON_UNESCAPED_UNICODE, русские символы будут иметь вид \u0438\u0432\u0430\u043d.

Как отправить JSON через GET-запрос?

Иногда требуется передать JSON-данные в query-параметрах, например для поисковых запросов. Сериализованный JSON добавляется к URL после знака вопроса.


$params = ['filter' => ['status' => 'active', 'age' => 25]];
$query = http_build_query(['data' => json_encode($params)]);
$url = 'https://api.example.com/search?' . $query;

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

Случаи использования: когда API ожидает данные в строке запроса (например, для кэширования). Недостаток – ограничение длины URL.

Проблема: если JSON содержит спецсимволы, они должны быть закодированы функцией urlencode. Использование http_build_query решает эту задачу автоматически.

Как отправить JSON с помощью библиотеки Guzzle (альтернатива cURL)?

Guzzle – популярный HTTP-клиент для PHP. Он предоставляет удобный интерфейс, автоматически устанавливает заголовки и обрабатывает JSON.


use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://api.example.com']);
$response = $client->post('/users', [
    'json' => ['name' => 'Иван', 'email' => 'ivan@example.com']
]);
$body = $response->getBody()->getContents();
$httpCode = $response->getStatusCode();

Пояснение: опция json автоматически кодирует массив в JSON, устанавливает Content-Type и обрабатывает ошибки. Подходит для проектов, где уже используется Composer.

Проблема: Guzzle может требовать установки через Composer и имеет больше зависимостей. Для простых скриптов cURL предпочтительнее.

Как отправить многомерный или вложенный JSON?

Для сложных структур данные формируются в виде многомерного массива, после чего json_encode обрабатывает их корректно.


$data = [
    'user' => [
        'name' => 'Петр',
        'contacts' => [
            ['type' => 'email', 'value' => 'petr@mail.com'],
            ['type' => 'phone', 'value' => '+71234567890']
        ]
    ],
    'meta' => ['source' => 'web']
];

$json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
// отправка через cURL как в основном примере

Важно: флаг JSON_PRETTY_PRINT делает JSON читаемым, но увеличивает размер. Для production лучше не использовать.

Ошибка: если данные содержат объекты (stdClass) или ресурсы, json_encode может вернуть false. Следует проверять результат: if ($json === false) { echo json_last_error_msg(); }.

Как отправить JSON с аутентификацией (Bearer token)?

Для защищённых API необходимо добавить заголовок Authorization.


$token = 'your_bearer_token';
$headers = [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $token
];

$ch = curl_init('https://api.example.com/users');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
// ...

Случаи использования: работа с REST API, требующими токен (JWT, OAuth).

Проблема: токен может быть просрочен – необходима логика обновления. Также не следует хранить токен в коде – использовать переменные окружения.

Как обработать ответ сервера в случае ошибки?

Важно проверять HTTP-код ответа и декодировать JSON-ответ, который может содержать сообщение об ошибке.


$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if (curl_errno($ch)) {
    $errorMsg = curl_error($ch);
    // логирование или обработка
} elseif ($httpCode >= 400) {
    $errorBody = json_decode($response, true);
    $errorMessage = $errorBody['error']['message'] ?? 'Неизвестная ошибка';
    // обработка ошибки
} else {
    $result = json_decode($response, true);
}

Рекомендация: всегда использовать curl_error для обнаружения сетевых проблем и проверять HTTP-статус для бизнес-ошибок.

Общие проблемы и их решение

  • SSL certificate problem: при разработке можно отключить проверку SSL: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);. На production обязательно настроить правильные сертификаты (CA bundle).
  • Тайм-аут запроса: установить CURLOPT_TIMEOUT (секунды) и CURLOPT_CONNECTTIMEOUT.
  • Ограничение памяти при большом JSON: использовать поточную обработку или увеличить memory_limit.
  • Кодировка UTF-8: убедиться, что исходные данные в UTF-8. Флаг JSON_UNESCAPED_UNICODE помогает.

Расширенные примеры отправки JSON через cURL

Пример 1. Отправка JSON с авторизацией через Basic Auth

Пример

$data = ['login' => 'admin', 'password' => '12345'];
$json = json_encode($data);

$ch = curl_init('https://api.example.com/auth');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_USERPWD, 'admin:12345'); // Basic Auth
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

echo "HTTP код: " . curl_getinfo($ch, CURLINFO_HTTP_CODE) . "\n";
echo "Ответ: " . $response;
HTTP код: 200
Ответ: {"token":"eyJ..."}

Пример 2. Отправка JSON через прокси-сервер

Пример

$proxy = 'http://proxy.example.com:8080';
$proxyAuth = 'user:pass';

$ch = curl_init('https://api.example.com/data');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyAuth);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

Пример 3. Отправка JSON с помощью PUT (обновление ресурса)

Пример

$data = ['status' => 'updated'];
$json = json_encode($data);

$ch = curl_init('https://api.example.com/users/123');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

Пример 4. Отправка JSON с дополнительными заголовками (например, X-Request-Id)

Пример

$headers = [
    'Content-Type: application/json',
    'X-Request-Id: ' . uniqid(),
    'Accept: application/json'
];

$ch = curl_init('https://api.example.com/orders');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

Пример 5. Отправка JSON с управлением временем ожидания и редиректами

Пример

$ch = curl_init('https://api.example.com/data');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); // 5 секунд на соединение
curl_setopt($ch, CURLOPT_TIMEOUT, 10);        // 10 секунд на весь запрос
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // следовать редиректам
curl_setopt($ch, CURLOPT_MAXREDIRS, 2);          // ограничить количество редиректов
$response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);

echo "URL после редиректов: " . $info['url'];

Пример 6. Отправка большого JSON-файла из файла (поточная передача)

Пример

$filePath = '/tmp/large_data.json';
$handle = fopen($filePath, 'r');

$ch = curl_init('https://api.example.com/upload');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_INFILE, $handle);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($filePath));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
fclose($handle);

Пример 7. Отправка JSON с помощью cURL и обработка ответа в виде потока (stream)

Пример

$ch = curl_init('https://api.example.com/stream');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); // не возвращать, выводить напрямую
curl_setopt($ch, CURLOPT_FILE, fopen('php://output', 'w'));
$response = curl_exec($ch);
curl_close($ch);
// Данные выводятся на экран по мере получения

Пример 8. Параллельная отправка нескольких JSON-запросов (curl_multi)

Пример

$urls = [
    'https://api.example.com/item/1',
    'https://api.example.com/item/2',
    'https://api.example.com/item/3'
];
$jsonData = ['action' => 'update', 'value' => 42];
$json = json_encode($jsonData);

$mh = curl_multi_init();
$handles = [];

foreach ($urls as $i => $url) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_multi_add_handle($mh, $ch);
    $handles[$i] = $ch;
}

$running = null;
do {
    curl_multi_exec($mh, $running);
} while ($running > 0);

foreach ($handles as $ch) {
    $response = curl_multi_getcontent($ch);
    echo "Ответ: " . $response . "\n";
    curl_multi_remove_handle($mh, $ch);
    curl_close($ch);
}
curl_multi_close($mh);
Ответ: {"id":1,"status":"ok"}
Ответ: {"id":2,"status":"ok"}
Ответ: {"id":3,"status":"ok"}

Пример 9. Отправка JSON с автоматической обработкой ошибок и повторными попытками

Пример

function sendJsonWithRetry($url, $data, $maxRetries = 3) {
    $json = json_encode($data);
    $attempt = 0;
    do {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error === '' && $httpCode < 500) {
            return ['code' => $httpCode, 'body' => $response];
        }
        $attempt++;
        if ($attempt < $maxRetries) {
            usleep(1000000 * $attempt); // задержка 1,2,3 секунды
        }
    } while ($attempt < $maxRetries);

    return ['code' => 0, 'error' => 'Все попытки исчерпаны'];
}

$result = sendJsonWithRetry('https://api.example.com/try', ['test' => true]);
print_r($result);

Пример 10. Отправка JSON с указанием пользовательского User-Agent

Пример

$ch = curl_init('https://api.example.com/users');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'User-Agent: MyApp/1.0'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

Отправка JSON с помощью cURL в PHP - comments

En
Php curl application json (php)