JSON в PHP: json_encode и json_decode — практическое практическое руководство для начинающих

JSON в PHP: json_encode и json_decode — практическое практическое руководство для начинающих

JSON в PHP: json_encode и json_decode — практическое практическое руководство для начинающих

Запрос “JSON в PHP: json_encode, json_decode” стабильно в топе у начинающих. И недаром: именно через JSON большинство PHP‑приложений общаются с фронтендом и внешними сервисами. Разберем базу и лучшие практики: от правильных заголовков до флагов, ошибок и мини‑API без фреймворков.

Базовый пример: как отдать JSON из PHP

Главное — выставить корректный заголовок и закодировать данные в UTF‑8.

<?php
$data = [
  'ok' => true,
  'user' => ['id' => 42, 'name' => 'Иван'],
];

header('Content-Type: application/json; charset=utf-8');
// Не экранируем Юникод и слеши, чтобы строка была читаемой
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

По умолчанию json_encode экранирует русские буквы как u0418u0432… — флаги выше это исправляют.

json_encode: важные флаги, о которых забывают

  • JSON_UNESCAPED_UNICODE — не экранировать Unicode (удобнее читать).
  • JSON_UNESCAPED_SLASHES — не экранировать / в URL.
  • JSON_PRETTY_PRINT — форматировать вывод (для логов/отладки).
  • JSON_PRESERVE_ZERO_FRACTION — сохранить 0.0 как число с дробной частью.
  • JSON_INVALID_UTF8_SUBSTITUTE — заменить битые байты на � вместо фатала.
  • JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS|JSON_HEX_QUOT — безопасная встраивка JSON в HTML.
  • <?php
    $city = ['city' => 'Москва', 'url' => 'https://example.com/a/b'];
    echo json_encode($city, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
    
    $price = ['price' => 10.0, 'discount' => 0.0];
    echo json_encode($price, JSON_PRESERVE_ZERO_FRACTION); // 0.0 сохранится как 0.0
    
    $bad = ['text' => "Invalid xC3"];
    echo json_encode($bad, JSON_INVALID_UTF8_SUBSTITUTE);
    

    json_decode: массив или объект, глубина и большие числа

    json_decode по умолчанию возвращает объект stdClass. Чтобы получить ассоциативный массив, передайте true вторым параметром.

    <?php
    $json = '{"ok":true,"user":{"id":42,"name":"Иван"}}';
    
    // Ассоциативный массив
    $arr = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
    // Объект stdClass
    $obj = json_decode($json, false, 512, JSON_THROW_ON_ERROR);
    

    Параметр глубины (по умолчанию 512) защищает от слишком вложенных структур. Для очень больших чисел используйте JSON_BIGINT_AS_STRING — иначе число может потерять точность.

    <?php
    $json = '{"id": 9223372036854775808}'; // больше, чем PHP_INT_MAX
    $assoc = json_decode($json, true, 512, JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING);
    var_dump($assoc['id']); // string(19) "9223372036854775808"
    

    Безопасная обработка ошибок: JSON_THROW_ON_ERROR

    Старый способ — проверять json_last_error(). Современный и удобный — ловить JsonException с флагом JSON_THROW_ON_ERROR.

    <?php
    try {
      // Ошибка: лишняя запятая
      $data = json_decode('{"a":1,}', true, 512, JSON_THROW_ON_ERROR);
    } catch (JsonException $e) {
      http_response_code(400);
      echo json_encode(['error' => $e->getMessage()], JSON_UNESCAPED_UNICODE);
    }
    

    Мини‑API на чистом PHP: принимаем и отдаем JSON

    Пример обработчика POST /greet, который принимает JSON {«name»: «Иван»} и возвращает приветствие.

    <?php
    declare(strict_types=1);
    
    header('Content-Type: application/json; charset=utf-8');
    
    if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
      http_response_code(405);
      echo json_encode(['error' => 'Method Not Allowed'], JSON_UNESCAPED_UNICODE);
      exit;
    }
    
    if (stripos($_SERVER['CONTENT_TYPE'] ?? '', 'application/json') !== 0) {
      http_response_code(415);
      echo json_encode(['error' => 'Expected application/json'], JSON_UNESCAPED_UNICODE);
      exit;
    }
    
    $raw = file_get_contents('php://input');
    try {
      $in = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
    } catch (JsonException $e) {
      http_response_code(400);
      echo json_encode(['error' => 'Invalid JSON', 'details' => $e->getMessage()], JSON_UNESCAPED_UNICODE);
      exit;
    }
    
    $name = trim((string)($in['name'] ?? 'Гость'));
    $out = ['ok' => true, 'greeting' => "Привет, $name"]; 
    
    echo json_encode($out, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    

    Такой скрипт можно запускать на встроенном веб‑сервере PHP для локальной отладки: php -S localhost:8000.

    Частые ошибки и как их избежать

  • Нет заголовка Content-Type. Браузер и клиенты не понимают, что это JSON. Всегда отправляйте header(‘Content-Type: application/json; charset=utf-8′).
  • Двойное кодирование. Нельзя передавать в json_encode уже закодированную строку JSON — получите строки в кавычках внутри JSON.
  • Потеря нулей после запятой. Добавляйте JSON_PRESERVE_ZERO_FRACTION, если важно 0.0 vs 0.
  • Числовые строки становятся числами. Флаг JSON_NUMERIC_CHECK в encode преобразует строки вида «00123» в число 123 — аккуратно с артикульными кодами/телефонами.
  • Большие числа ломаются. При decode используйте JSON_BIGINT_AS_STRING, иначе потеря точности неизбежна.
  • Битая кодировка. Следите, чтобы входные строки были в UTF‑8; при encode добавляйте JSON_INVALID_UTF8_SUBSTITUTE.
  • Вывод до заголовков. Любой echo до header() ломает заголовки. Используйте буферизацию или выводите строго после header().
  • Встраивание JSON в HTML. Экранируйте опасные символы флагами JSON_HEX_*.
  • Полезные приемы

    Безопасная встраиваемая переменная в HTML:

    <?php
    $state = [
      'csrf' => bin2hex(random_bytes(16)),
      'user' => ['id' => 1, 'name' => '<script>alert(1)</script>'],
    ];
    $json = json_encode($state, JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_UNESCAPED_UNICODE);
    ?>
    <script>
      window.__STATE__ = <?php echo $json; ?>;
    </script>
    

    Построчная передача больших данных (NDJSON):

    <?php
    header('Content-Type: application/x-ndjson; charset=utf-8');
    foreach ($rows as $row) {
      echo json_encode($row, JSON_UNESCAPED_UNICODE), "n";
      flush();
    }
    

    Итоги

    Запомните основу: правильный Content-Type, нужные флаги encode/decode, и обработка ошибок через JSON_THROW_ON_ERROR. Этого достаточно, чтобы уверенно работать с JSON в PHP и писать аккуратные API.

    Хотите системно прокачаться и пройти путь от основ до продвинутых тем (PDO, безопасность, MySQL, практика)? Тогда загляните в курс: Пройти практический курс «PHP и MySQL с Нуля до Гуру 3.0» →

    Источник

    НЕТ КОММЕНТАРИЕВ

    Оставить комментарий