Как обработать JSON-запросы в PHP?php-26

JSON (JavaScript Object Notation) стал стандартом для обмена данными в веб-приложениях. Вот как правильно работать с JSON-запросами в PHP.

Получение JSON-данных из запроса

1. Чтение входных данных

$jsonData = file_get_contents('php://input');
$data = json_decode($jsonData, true); // true для ассоциативного массива

if (json_last_error() !== JSON_ERROR_NONE) {
    http_response_code(400);
    die(json_encode(['error' => 'Invalid JSON']));
}

2. Проверка заголовка Content-Type

if ($_SERVER['CONTENT_TYPE'] !== 'application/json') {
    http_response_code(415); // Unsupported Media Type
    die(json_encode(['error' => 'Content-Type must be application/json']));
}

Отправка JSON-ответа

Базовый пример

header('Content-Type: application/json');
echo json_encode([
    'status' => 'success',
    'data' => ['id' => 123, 'name' => 'John Doe']
]);

С обработкой ошибок

function jsonResponse($data, $statusCode = 200) {
    header('Content-Type: application/json');
    http_response_code($statusCode);
    echo json_encode($data, JSON_UNESCAPED_UNICODE);
}

try {
    $result = processData($inputData);
    jsonResponse(['data' => $result]);
} catch (Exception $e) {
    jsonResponse(['error' => $e->getMessage()], 500);
}

Обработка разных типов JSON-запросов

1. POST-запрос с JSON

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $input = json_decode(file_get_contents('php://input'), true);
    // Обработка данных
}

2. GET-параметры с JSON

if (isset($_GET['filters'])) {
    $filters = json_decode($_GET['filters'], true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        // Обработка ошибки
    }
}

3. PATCH/PUT-запросы

if (in_array($_SERVER['REQUEST_METHOD'], ['PATCH', 'PUT'])) {
    $input = json_decode(file_get_contents('php://input'), true);
    // Частичное/полное обновление
}

Безопасная обработка JSON

  1. Валидация данных:

    if (!isset($data['email']) || !filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
        throw new InvalidArgumentException('Invalid email');
    }
    
  2. Ограничение глубины:

    $data = json_decode($json, true, 10); // Максимальная глубина 10 уровней
    
  3. Экранирование спецсимволов:

    echo json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
    

Пример REST-эндпоинта

header('Content-Type: application/json');

try {
    // Проверка метода
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        throw new RuntimeException('Method Not Allowed', 405);
    }

    // Получение данных
    $input = json_decode(file_get_contents('php://input'), true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        throw new RuntimeException('Invalid JSON', 400);
    }

    // Валидация
    if (empty($input['username'])) {
        throw new InvalidArgumentException('Username is required', 400);
    }

    // Обработка
    $user = createUser($input['username']);

    // Ответ
    http_response_code(201);
    echo json_encode([
        'id' => $user->id,
        'username' => $user->username
    ]);

} catch (InvalidArgumentException $e) {
    http_response_code($e->getCode() ?: 400);
    echo json_encode(['error' => $e->getMessage()]);
} catch (Exception $e) {
    http_response_code($e->getCode() ?: 500);
    echo json_encode(['error' => $e->getMessage()]);
}

Работа с JSON в современных фреймворках

Laravel пример:

// Получение данных
$data = $request->json()->all();

// Ответ
return response()->json([
    'status' => 'success',
    'data' => $result
], 201);

Symfony пример:

use Symfony\Component\HttpFoundation\JsonResponse;

// Ответ
return new JsonResponse(
    ['data' => $result],
    JsonResponse::HTTP_CREATED
);

Резюмируем:

для работы с JSON в PHP используйте json_decode() для входящих данных и json_encode() для ответов. Всегда проверяйте Content-Type, валидируйте входные данные и обрабатывайте ошибки. В фреймворках используйте встроенные методы для более удобной работы с JSON.