json_encode и json_decode: работа с JSON
JSON — текстовый формат для обмена данными между программами: в нём сайт отдаёт данные JavaScript на странице и мобильным приложениям. В PHP строку JSON делает json_encode, а читает json_decode:
<?php
$user = ['name' => 'Анна', 'age' => 25, 'langs' => ['php', 'sql']];
echo json_encode($user) . "\n";
echo json_encode($user, JSON_UNESCAPED_UNICODE) . "\n";{"name":"\u0410\u043d\u043d\u0430","age":25,"langs":["php","sql"]}
{"name":"Анна","age":25,"langs":["php","sql"]}json_encode превращает массив или объект PHP в строку JSON. По умолчанию русские буквы записываются кодами вида \u0410 (это «А») — это правильный JSON, но читать его неудобно. Флаг JSON_UNESCAPED_UNICODE оставляет буквы как есть. Ещё полезны:
JSON_PRETTY_PRINT— с переносами и отступами, для чтения человеком;JSON_UNESCAPED_SLASHES— не превращать/в\/(это удобно для адресов);JSON_THROW_ON_ERROR— при ошибке выбросить исключение, а не вернутьfalse.
Флаги складываются через |:
<?php
$user = ['name' => 'Анна', 'langs' => ['php', 'sql']];
echo json_encode($user, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";{
"name": "Анна",
"langs": [
"php",
"sql"
]
}Список с ключами 0, 1, 2… становится массивом JSON […], а массив со строковыми ключами — объектом {…}.
Из JSON в PHP
<?php
$json = '{"title": "Новости", "count": 3, "tags": ["минск", "погода"]}';
$data = json_decode($json, true);
echo $data['title'] . "\n";
echo ($data['count'] + 1) . "\n";
echo implode(', ', $data['tags']) . "\n";Новости
4
минск, погодаВторой аргумент true — получить ассоциативный массив. Без него json_decode вернёт объект, и к полям обращаются через стрелку: $data->title.
Ошибки разбора
Если строка — не JSON, json_decode вернёт null. Но null бывает и правильным значением ('null'), поэтому надёжнее включить исключения:
<?php
$input = '{"title": "без закрывающей скобки"';
try {
$data = json_decode($input, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo 'Неверный JSON: ' . $e->getMessage() . "\n";
}Третий аргумент 512 — допустимая глубина вложенности (значение по умолчанию; его приходится указывать, чтобы дойти до четвёртого аргумента с флагами). Без исключений причину последней ошибки показывает json_last_error_msg(). В PHP 8.3 появилась функция json_validate, которая только проверяет строку.
JSON в ответе сайта (API)
API — адреса сайта, которые отвечают не страницей для человека, а данными для программ:
<?php
$result = ['ok' => true, 'items' => [['id' => 1, 'title' => 'Хлеб']]];
header('Content-Type: application/json; charset=utf-8');
echo json_encode($result, JSON_UNESCAPED_UNICODE);Заголовок Content-Type сообщает браузеру или программе, что пришёл JSON. Тело запроса с JSON (так его отправляет JavaScript через fetch) в $_POST не попадает — его читают целиком:
<?php
$body = json_decode(file_get_contents('php://input'), true);Подводные камни
- Не UTF-8. Строки в кодировке Windows-1251
json_encodeне примет: вернётfalseс ошибкойMalformed UTF-8 characters. Храните текст в UTF-8. - Пустой массив.
json_encode([])даёт[], а не{}. Если нужен пустой объект, передайтеnew stdClass()или флагJSON_FORCE_OBJECT. - Дырявый список. После
unsetу списка ключи 0, 2, 3 — и он превратится в объект{"0":…,"2":…}. Перенумеруйте его черезarray_valuesперед кодированием. - Данные от посетителя. Значения из разобранного JSON проверяйте так же, как поля формы: их прислал не ваш код.