JSON Toolkit

Почему китайский превращается в \u4e2d\u6587

Главное: Escape-последовательность \u4e2d\u6587 — это легитимный Unicode, а не сбой кодировки. Настоящее искажение выглядит иначе, и различение решает, что именно нужно исправлять.

Начинающий~3 мин чтенияОпубликовано 2026-10-30Обновлено 2026-10-30
Unicode-экранирование против настоящего искажения кодировки в JSON

Главное: считайте вывод \uXXXX легитимным экранированием, подтвердите, что он проходит туда-обратно через JSON.parse, и отключите чисто-ASCII сериализацию вроде ensure_ascii=False, когда нужен читаемый китайский; сохраняйте экранирование только для транспортов, не способных нести не-ASCII.

Потому что он был экранирован, а не повреждён.

JSON.parse('"\\u4e2d\\u6587"')  // "中文"

\u4e2d — это 中, а \u6587 — это 文. Это легитимные escape-последовательности; любой парсер их восстанавливает. Ничего не сломано — просто нечитаемо в логах, различиях и захватах пакетов.

Кто делает экранирование

Инструмент По умолчанию Переключатель
Python json.dumps Экранирует (ensure_ascii=True) ensure_ascii=False
JavaScript JSON.stringify Не экранирует —
Java Jackson Не экранирует Опционально
PHP json_encode Не экранирует с 5.4 —
Go encoding/json Не экранирует —

Python — безусловно самый частый источник. Значение по умолчанию существует по причине: чисто-ASCII вывод выживает в любом транспорте. Цена — каждый не-ASCII символ становится шестью символами.

Экранирование против искажения

Экранирование: \u4e2d\u6587, соответствует \uXXXX. Вызвано настройками сериализатора. Искажение: 测试, 涓枃. Вызвано записью UTF-8-байтов и чтением их как Latin-1 или GBK.

Быстрый тест: вставьте текст в консоль браузера как JSON.parse('"…"'). Если он возвращается читаемым, это было экранирование. Если падает или остаётся искажённым, это несовпадение кодировок — и исправление в том, чтобы выровнять кодировки, а не трогать сериализатор.

Отключение

json.dumps(data, ensure_ascii=False)

Затем проверьте нижестоящие системы: некоторые устаревшие системы действительно рассчитывают на чисто-ASCII транспорт, особенно SMS-шлюзы и старые почтовые релеи.

Когда экранирование — правильный выбор

  • Транспорты, враждебные к не-ASCII (устаревшие HTTP-заголовки, некоторые SMS-шлюзы)
  • JSON, вложенный внутрь другой строки JSON, где экранирование уменьшает конфликты кавычек
  • Конвейеры логов, которые обрезают по байтам и разорвали бы многобайтовый символ

В остальном предпочитайте читаемость и отключите его.

Вопросы и ответы

Почему Python по умолчанию экранирует китайский?

Потому что ensure_ascii=True — значение по умолчанию, гарантирующее чисто-ASCII вывод, который выживает в любом транспорте. Цена — каждый не-ASCII символ становится шестью символами.

Стоит ли отключать ensure_ascii?

Отключайте, когда важна читаемость. Затем проверьте нижестоящие системы — устаревшие HTTP-заголовки, некоторые SMS-шлюзы и конвейеры логов, обрезающие по байтам, могут всё ещё рассчитывать на чисто-ASCII содержимое.

Что происходит, если транспорт не может нести не-ASCII?

Сохраняйте экранирование. Когда JSON вложен внутрь другой строки JSON или идёт через канал, враждебный к не-ASCII, экранирование избегает конфликтов кавычек и предотвращает разрыв многобайтовых символов.

Дополнительное чтение