Как получить и обработать JSON данные из POST запроса в PHP?
Правильный способ получения JSON из POST запроса
Вы абсолютно правы — для получения JSON данных через POST запрос в PHP нельзя использовать суперглобальный массив $_POST. Он заполняется только при отправке данных в формате application/x-www-form-urlencoded или multipart/form-data. Когда клиент отправляет JSON с заголовком Content-Type: application/json, PHP не парсит его автоматически.
Для получения "сырого" тела запроса используется поток php://input. Вот правильная реализация:
<?php
// receive.php
// Получаем сырые данные из тела запроса
$json = file_get_contents('php://input');
// Проверяем, что данные получены
if ($json === false) {
http_response_code(400);
echo json_encode(['error' => 'Не удалось прочитать тело запроса']);
exit;
}
// Декодируем JSON в массив (второй параметр true)
$data = json_decode($json, true);
// Проверяем ошибки декодирования
if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(400);
echo json_encode([
'error' => 'Некорректный JSON',
'details' => json_last_error_msg()
]);
exit;
}
// Теперь можно работать с данными
$name = $data['name'] ?? null;
$email = $data['email'] ?? null;
$age = $data['age'] ?? null;
// Пример сохранения в файл
file_put_contents('log.txt', print_r($data, true));
// Отправляем ответ клиенту
http_response_code(200);
echo json_encode([
'status' => 'success',
'message' => 'Данные получены',
'received' => $data
]);
?>
Ключевые моменты
- file_get_contents('php://input') — читает всё тело запроса как строку
- json_decode($json, true) — преобразует JSON строку в ассоциативный массив PHP
- Всегда проверяйте ошибки с помощью json_last_error()
- Используйте http_response_code() для корректной обработки ошибок
Дополнительные рекомендации
Если вы используете современные фреймворки (Laravel, Symfony), они уже имеют встроенные методы для работы с JSON. Но чистый PHP требует ручного парсинга. Вот ещё один пример с обработкой разных Content-Type:
<?php
// Универсальный обработчик
function getRequestData() {
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
if (stripos($contentType, 'application/json') !== false) {
// JSON запрос
$json = file_get_contents('php://input');
return json_decode($json, true) ?? [];
}
// Обычная форма
return $_POST;
}
$data = getRequestData();
// Дальше работаем с $data как с обычным массивом
?>
Тестирование через Postman
Убедитесь, что в Postman вы:
- Выбрали метод POST
- В Body выбрали "raw" и формат JSON
- Добавили заголовок
Content-Type: application/json(Postman добавляет его автоматически при выборе JSON)
После этого ваш скрипт будет корректно принимать и обрабатывать JSON данные.
<<Альтернативный подход с использованием потоков
Можно также использовать более гибкий способ чтения данных через потоковый интерфейс, особенно если вы ожидаете большие объёмы JSON данных:
<?php
// Чтение через поток
$stream = fopen('php://input', 'r');
$json = stream_get_contents($stream);
fclose($stream);
$data = json_decode($json, true);
// Проверка
if (is_array($data) && !empty($data)) {
// Обработка данных
$response = [
'name' => htmlspecialchars($data['name'] ?? ''),
'email' => filter_var($data['email'] ?? '', FILTER_VALIDATE_EMAIL)
];
echo json_encode(['success' => true, 'data' => $response]);
} else {
http_response_code(400);
echo json_encode(['success' => false, 'error' => 'Некорректные данные']);
}
?>
Этот метод особенно полезен, если вы работаете с большими полезными нагрузками, так как позволяет читать данные частями. Однако для большинства случаев file_get_contents() более чем достаточно.
Важно помнить: php://input доступен только для чтения один раз за запрос. Если вы прочитали его в одном месте скрипта, повторное чтение вернёт пустую строку. Поэтому всегда сохраняйте результат в переменную.