#Что происходит и как определить неисправность
В JSON символы кириллицы могут записываться как последовательности вида \u041f — это допустимое представление Юникода, а не испорченный текст. Если нужен читаемый JSON, в PHP используется флаг JSON_UNESCAPED_UNICODE при условии корректной UTF-8-строки.
#Вероятные причины и признаки
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Обычное экранирование по умолчаниюОбычное экранирование по умолчанию. JSON содержит \uXXXX, но json_decode() возвращает правильную русскую строку | JSON содержит \uXXXX, но json_decode() возвращает правильную русскую строку | Использовать JSON_UNESCAPED_UNICODE при формировании. |
| Исходная строка не в UTF-8Исходная строка не в UTF-8. json_encode() выдаёт false/исключение или повреждённую строку | json_encode() выдаёт false/исключение или повреждённую строку | Исправить кодировку входных данных, а не отключать проверки. |
| Дополнительный сериализатор меняет результатДополнительный сериализатор меняет результат. Файл был записан корректно, но после экспорта появляется двойное экранирование | Файл был записан корректно, но после экспорта появляется двойное экранирование | Проверить этап записи и повторного преобразования JSON. |
#Пошаговая диагностика и исправление
- Отличите экранирование от поврежденияОткройте JSON в текстовом редакторе с UTF-8. Если видите \u041f\u0440..., декодируйте небольшое тестовое значение стандартным JSON-парсером: если получается корректный русский текст, данные не утрачены. Если вместо букв видны «РџС...», это иная проблема перекодировки.
- Проверьте входные данныеУзнайте, в какой кодировке пришла строка из базы, HTTP-запроса или старого файла. Для JSON стандарт требует UTF-8; не применяйте mb_convert_encoding к уже правильно закодированным данным. Сверьте кодировку подключения к базе и исходного файла.
- Примените правильный параметр json_encodeНа тестовой копии в редакторе замените вызов json_encode($data) на вариант с JSON_UNESCAPED_UNICODE. При необходимости для удобства чтения добавьте JSON_PRETTY_PRINT, но помните: форматирование изменит размер файла.
- Пример кода по темеPHPПример PHP 7.3+ на тестовой копии; записывает файл sample.json и требует разрешённый каталог.
<?php $data = ["message" => "Привет"]; $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR); file_put_contents(__DIR__ . "/sample.json", $json);
- Запишите исключения вместо молчаливого отказаЕсли приложение использует PHP 7.3+, оберните json_encode в try/catch (JsonException), записывая в закрытый журнал только техническое сообщение без содержимого персональных данных. На старых версиях проверяйте возвращаемое false через json_last_error_msg.
- Проверьте отсутствие двойной сериализацииОткройте итоговый файл и убедитесь, что его корневой тип соответствует ожидаемому объекту/массиву. Если весь JSON окружён кавычками и внутри много \" и \\, возможно, JSON-кодировали повторно как строку. Исправьте именно второй вызов, не выполняйте массовую замену обратных слешей.
- Сверьте HTTP-заголовок и файлЕсли JSON отдаётся по сети, проверьте Content-Type: application/json и правильную кодировку документа. Вручную не вставляйте непроверенную строку пользователя в JSON через конкатенацию: так можно нарушить синтаксис и экранирование управляющих символов.
- Прочитайте результат обратноНа тестовом файле выполните json_decode с JSON_THROW_ON_ERROR и сравните исходную строку с полученной. Для рабочего массива проверьте несколько русских букв, кавычки, перевод строки и эмодзи. После проверки удалите sample.json, если он не нужен.
- Не ломайте совместимость ради читаемостиЕсли существующий API ожидает стандартный JSON, менять способ экранирования необязательно: оба варианта допустимы. Зафиксируйте изменение для команды, обновите тесты и проверьте клиентов до публикации.
#Как проверить результат
После нового экспорта в тексте видны кириллические символы, json_decode успешно возвращает исходные значения, API и проверка схемы не изменились.
#Если не помогло
При ошибке UTF-8 проверьте кодировку источника; при двойных слешах — количество вызовов кодирования. Не заменяйте слеши регулярными выражениями во всём файле.