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 экранирует русские буквы как \u0418\u0432... — флаги выше это исправляют.
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» →
-
Создано 06.04.2026 17:01:29
-
Михаил Русаков

Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.