Menu

PHP json_encode(): массивы и объекты в JSON

json_encode($value) превращает массив, объект или скаляр PHP в строку JSON. Ассоциативные массивы становятся JSON-объектами, списки JSON-массивами, а флаги вроде JSON_PRETTY_PRINT и JSON_UNESCAPED_UNICODE управляют выводом.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

json_encode($value) возвращает JSON-текст для значения PHP. Ассоциативный массив становится JSON-объектом, список (ключи 0, 1, 2...) JSON-массивом, а строки, числа, true, false и null становятся своими эквивалентами в JSON.

Вывод:

{"name":"Ada","age":36,"langs":["php","js"],"admin":true,"manager":null}
string

Результат это обычная строка, готовая к отправке в браузер, сохранению в файл или столбец базы данных или передаче другой программе. Чтобы превратить JSON обратно в PHP, используйте json_decode().

Красивый вывод JSON

json_encode() принимает флаги вторым аргументом. JSON_PRETTY_PRINT добавляет переносы строк и отступы в 4 пробела, и именно это нужно в файле настроек или отладочном логе. Несколько флагов объединяются через |:

Вывод:

{
    "app": "shop",
    "debug": false,
    "db": {
        "host": "localhost",
        "port": 3306
    },
    "tags": []
}

Читаемый японский, русский и другой текст в UTF-8

По умолчанию json_encode() записывает каждый не-ASCII символ escape-последовательностью \u и ставит обратный слеш перед каждым /. И то, и другое корректный JSON и декодируется обратно в тот же текст, но вывод становится длиннее и хуже читается. JSON_UNESCAPED_UNICODE сохраняет символы, а JSON_UNESCAPED_SLASHES оставляет URL как есть:

Вывод:

{"name":"\u308a\u3093\u3054","price":120,"url":"https:\/\/example.com\/fruit\/apple"}
{"name":"りんご","price":120,"url":"https://example.com/fruit/apple"}

Если после декодирования текст выглядит как кракозябры, дело не в escape-последовательностях: строка изначально была не в UTF-8. json_encode() принимает только UTF-8 и для всего остального возвращает false, как показано в разделе об ошибках.

Когда массив становится объектом, а не списком

Массив PHP кодируется как JSON-массив, только когда его ключи ровно 0, 1, 2... по порядку. Любые другие ключи делают его JSON-объектом. На этом попадаются после unset() или array_filter(), которые оставляют пропуски в ключах:

Вывод:

{"0":"apple","2":"cherry"}
["apple","cherry"]
{"1":"a","2":"b"}
[]
{}
{"0":"a","1":"b"}

Вызывайте array_values() перед кодированием всякий раз, когда принимающий код ждёт список. Если он ждёт объект, который может быть пустым, используйте new stdClass() или (object) $array, чтобы пустое значение всё равно выходило как {}.

Кодирование объекта и управление его JSON через JsonSerializable

Обычный объект кодируется только со своими публичными свойствами; защищённые и закрытые пропускаются. Чтобы точно решать, как объект выглядит в JSON, реализуйте интерфейс JsonSerializable и возвращайте данные из jsonSerialize():

Вывод:

{"name":"Ada","nick":null}
{"date":"2026-03-14 09:30:00.000000","timezone_type":3,"timezone":"UTC"}
{
    "id": 7,
    "total": 19.5,
    "created": "2026-03-14T09:30:00+00:00"
}

Типизированное перечисление вроде enum Status: string кодируется своим значением ("active"). У чистого перечисления значения нет, поэтому json_encode() на нём падает с сообщением "Non-backed enums have no default serialization".

Числа, float и числовые строки

Целые числа и float записываются как JSON-числа, а строки остаются строками, даже если состоят из цифр. Три флага это меняют:

Вывод:

{"price":10}
{"price":10.0}
0.30000000000000004
{"qty":"3","id":"007"}
{"qty":3,"id":7}

JSON_NUMERIC_CHECK преобразует каждую числовую строку, поэтому ID вроде "007" или почтовый индекс вроде "01234" теряет ведущие нули. Преобразуйте нужные поля через (int), а не применяйте флаг ко всему массиву.

json_encode возвращает false: поиск ошибки

json_encode() возвращает false, когда не может закодировать значение. Обычные причины это строка, которая не является корректным UTF-8 (текст из старого файла или базы данных в Latin-1), и значения float NAN и INF. json_last_error_msg() сообщает, что пошло не так; JSON_THROW_ON_ERROR заставляет функцию выбрасывать JsonException:

Вывод:

bool(false)
Malformed UTF-8 characters, possibly incorrectly encoded
{"name":"Caf\ufffd"}
{"name":"Café"}
JsonException: Inf and NaN cannot be JSON encoded

JSON_THROW_ON_ERROR лучший вариант по умолчанию в новом коде: false, который никто не проверил, в итоге сохраняется или отправляется как пустая строка.

Ответ JSON из PHP API

PHP-скрипт, который отвечает JSON, устанавливает заголовок Content-Type до любого вывода, кодирует один раз и завершается:

<?php
header('Content-Type: application/json; charset=utf-8');

$products = [
    ['id' => 1, 'name' => 'りんご', 'price' => 120],
    ['id' => 2, 'name' => 'みかん', 'price' => 80],
];

echo json_encode(['data' => $products], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
exit;

Когда вы выводите JSON внутри HTML-тега <script>, добавьте JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT. Стандартное экранирование слешей превращает </script> в <\/script>, но эта защита исчезает, как только кто-то добавит JSON_UNESCAPED_SLASHES, а <!-- в значении всё равно меняет то, как браузер разбирает скрипт. Флаги записывают <, >, &, ' и " как \u003C, \u003E, \u0026, \u0027 и \u0022, а JavaScript читает их обратно как те же символы.

Часто задаваемые вопросы

Как преобразовать массив PHP в JSON?

Передайте его в json_encode(): json_encode(['name' => 'Ada', 'age' => 36]) возвращает {"name":"Ada","age":36}. Массив с ключами 0, 1, 2... по порядку становится JSON-массивом: json_encode(['a', 'b']) возвращает ["a","b"].

Как красиво отформатировать JSON в PHP?

Добавьте флаг JSON_PRETTY_PRINT: json_encode($data, JSON_PRETTY_PRINT) делает отступы в 4 пробела и ставит каждое значение на отдельную строку. Флаги объединяются через |, например JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE.

Почему json_encode превращает русский или японский текст в коды \u?

По умолчанию каждый не-ASCII символ записывается escape-последовательностью \uXXXX, поэтому りんご становится \u308a\u3093\u3054. Это по-прежнему корректный JSON, но передайте JSON_UNESCAPED_UNICODE, чтобы символы оставались читаемыми.

Почему json_encode возвращает false?

Обычно потому, что строка не является корректным UTF-8 или в данных есть NAN или INF. Вызовите json_last_error_msg(), чтобы увидеть причину, или передайте JSON_THROW_ON_ERROR, чтобы функция выбрасывала JsonException вместо возврата false.

Как заставить json_encode выводить {} вместо [] для пустого массива?

Пустой массив PHP всегда кодируется как []. Для пустого объекта используйте new stdClass() или (object) [] либо флаг JSON_FORCE_OBJECT, который превращает в объект каждый массив в значении.

Иллюстрация языков программирования Coddy

Учитесь программировать с Coddy

НАЧАТЬ