Как поменять кодировку в json файле

Обновлено: 04.07.2024

Проблема: она не читается человеком. Мои (умные) пользователи хотят проверять или даже редактировать текстовые файлы с помощью дампов JSON (и я бы предпочел не использовать XML).

Есть ли способ сериализации объектов в строки JSON UTF-8 (вместо \uXXXX )?

Используйте ensure_ascii=False переключатель, чтобы json.dumps() затем кодировать значение в UTF-8 вручную:

Если вы пишете в файл, просто используйте json.dump() и оставьте его объекту file для кодирования:

Предостережения для Python 2

Для Python 2 есть еще несколько предостережений, которые необходимо учитывать. Если вы записываете это в файл, вы можете использовать его io.open() вместо того, open() чтобы создавать объект файла, который кодирует значения Unicode для вас при записи, а затем использовать json.dump() вместо этого запись в этот файл:

Обратите внимание , что существует ошибка в json модуле , где ensure_ascii=False флаг может производить смесь из unicode и str объектов. Обходной путь для Python 2:

В Python 2 при использовании байтовых строк (тип str ), закодированных в UTF-8, обязательно также установите encoding ключевое слово:

Написать в файл

Для печати на стандартный вывод

Спасибо! Я не понимал, что это было так просто. Вам нужно быть осторожным только в том случае, если данные, которые вы конвертируете в json, не заслуживают доверия со стороны пользователя. @ Габриэль, честно говоря, я не помню. Это не было чем-то настолько важным, чтобы отложить отрывок :( Работал только для меня, используя codecs библиотеку. Спасибо!

ОБНОВЛЕНИЕ: Это неправильный ответ, но все же полезно понять, почему это неправильно. Смотрите комментарии.

Как насчет unicode-escape ?

unicode-escape не обязательно: вы можете использовать json.dumps(d, ensure_ascii=False).encode('utf8') вместо этого. И не гарантируется, что json во всех случаях будет использовать те же правила, что и unicode-escape кодек в Python, т. Е. Результат может совпадать или не совпадать в некоторых угловых случаях. Понижение - за ненужное и, возможно, неправильное обращение. Несвязанный: работает только для языков utf8 или если envvar задает здесь utf8 (вместо этого выведите Unicode). print json_str PYTHONIOENCODING Другая проблема: любые двойные кавычки в строковых значениях потеряют свое экранирование, поэтому это приведет к некорректному выводу JSON . ошибка в Python3: AttributeError: у объекта 'str' нет атрибута 'decode' Unicode-escape отлично работает! Я бы принял этот ответ как правильный. @jfs Нет, json.dumps(d, ensure_ascii=False).encode('utf8') не работает, по крайней мере для меня. Я получаю UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position . ошибку. unicode-escape Вариант работает отлично однако.

Обходной путь Peters 2 для Python 2 завершается неудачно:

Это было сбой в части .decode ('utf8') строки 3. Я исправил проблему, сделав программу намного проще, избегая этого шага, а также особый корпус ascii:

«Краевой случай» был просто глупой непроверенной ошибкой с моей стороны. Ваш unicode(data) подход является лучшим вариантом, чем использование обработки исключений. Обратите внимание, что encoding='utf8' ключевое слово аргумент не имеет ничего общего с выводом, который json.dumps() производит; используется для декодирования str входных данных, которые получает функция. @MartijnPieters: или проще: open('filename', 'wb').write(json.dumps(d, ensure_ascii=False).encode('utf8')) он работает независимо от того, dumps возвращает ли (только для ascii) объект str или unicode. @JFSebastian: верно, потому что сначала str.encode('utf8') декодируется неявно. Но так же unicode(data) , если дан str объект. :-) Использование io.open() дает вам больше возможностей, включая использование кодека, который записывает спецификацию, и вы отслеживаете данные JSON чем-то другим. @MartijnPieters: .encode('utf8') вариант на основе работает как на Python 2 и 3 (один и тот же код). На unicode Python 3 нет. Не имеет отношения: файлы json не должны использовать BOM (хотя подтверждающий анализатор json может игнорировать BOM, см. Ошибку 3983 ). добавление encoding='utf8' к json.dumps решает проблему. PS У меня есть текст на кириллице

Начиная с Python 3.7, следующий код работает нормально:

Следующее мое понимание var читая ответ выше и гугл.

Вот мое решение с использованием json.dump ():

где SYSTEM_ENCODING установлен в:

Используйте кодеки, если это возможно,

Спасибо за оригинальный ответ здесь. С python 3 следующая строка кода:

было хорошо Попробуйте не писать слишком много текста в коде, если это не обязательно.

в основном установите he_IL или любой другой языковой стандарт на Ubuntu, проверьте, что он не установлен

установите его там, где XX ваш язык

добавьте следующий текст в / etc / apache2 / envvrs

Чем, надеюсь, вы не получите ошибок Python от Apache, например:

print (js) UnicodeEncodeError: кодек «ascii» не может кодировать символы в позиции 41-45: порядковый номер не в диапазоне (128)

Также в apache попробуйте сделать utf кодировкой по умолчанию, как описано здесь:
Как изменить кодировку по умолчанию на UTF-8 для Apache?

Сделайте это рано, потому что ошибки apache могут быть болезненными для отладки, и вы можете ошибочно думать, что это от python, что, возможно, не так в этой ситуации

Если вы загружаете строку JSON из файла и содержимое файла арабскими текстами. Тогда это будет работать.

сделанный! Теперь мы можем получить результаты в виде индекса JSON с арабским значением.

Использование sure_ascii = False в json.dumps - правильное направление для решения этой проблемы, как отметил Мартейн. Однако это может вызвать исключение:

Вам нужны дополнительные настройки в site.py или sitecustomize.py, чтобы правильно настроить sys.getdefaultencoding (). site.py находится в lib / python2.7 /, а sitecustomize.py находится в lib / python2.7 / site-packages.

Если вы хотите использовать site.py, в def setencoding (): измените первое, если 0: на, если 1: так, чтобы python использовал локаль вашей операционной системы.

Если вы предпочитаете использовать sitecustomize.py, который может не существовать, если вы его еще не создали. просто поместите эти строки:

Затем вы можете сделать некоторые китайские выходные данные в формате json в формате utf-8, например:

Вы получите строку в кодировке utf-8 вместо \ u экранированной строки json.

Подробную документацию всегда можно найти по этой ссылке:

Кодирование при помощи функции json_encode

Функция работает только с кодировкой UTF-8.

Рассмотрим простой пример:

Результат выполнения кода:

Как видим ассоциативный массив превратился в обычную json строку.

Более сложный пример:

Результат выполнения кода:

Что произошло c кириллицей?

Дело в том, что по умолчанию многобайтовые символы Unicode кодируются как \uXXXX. При раскодировании функцией json_decode они преобразуются в нормальные строки. В некоторых случаях мы можем захотеть избежать этого экранирования, например, чтобы посмотреть как выглядит наш JSON.

Для этого воспользуемся флагом JSON_UNESCAPED_UNICODE:

Получаем такой результат:

Мы может еще в целях изучения кода преобразовать его в более человеческий вид, при помощи дополнительного флага JSON_PRETTY_PRINT

Получаем такой результат:

Мы разобрались, как кодировать наши переменные в формат JSON при помощи json_encode.

Декодирование c помощью json_decode

Допустим у нас есть строка в формате JSON. Возьмем ее из предыдущего примера:

Давайте раскодируем ее:

У нас получился результат:

Как нам все таки получить обычный массив? Нужно в json_decode передать вторым параметром true:

Теперь мы получили обычный массив. Таким образом разобрались как работать с функцией json_decode для декодирования строки формата JSON.

Обработка ошибок

В случае ошибки, эти функции просто молча возвращают null.

Мы можем проверить, что нам вернулось null и посмотреть какая произошла ошибка следующим образом:

Иногда нам может быть полезно не молчаливо возвращать null, а выкинуть Exception и обработать его. PHP >7.3 предоставляет нам такую возможность.

Это можно сделать при помощи флага JSON_THROW_ON_ERROR

Более подробно про обработку ошибок JSON:

Как вывести JSON ответ на ajax запрос

Когда к нашему PHP скрипту обращается например javascript с ajax запросом, для того, чтобы подгрузить на страницу новые данные, то часто возникает необходимость ответить в формате JSON.

Содержимое файла text_json.php

Тем временем в javascript мы можем обратиться к нашему php скрипту таким образом:

Отправка JSON запросов на другой сервер.

Спасибо за внимание. Если после прочтения у вас остались вопросы - напишите какие.

json_encode

Returns a string containing the JSON representation of value.

JSON (англ. JavaScript Object Notation) - текстовый формат обмена данными, основанный на JavaScript и обычно используемый именно с этим языком. Как и многие другие текстовые форматы, JSON легко читается людьми.

Список параметров

The value being encoded. Can be any type except a resource .

Возвращаемые значения

Возвращает данные в формате JSON string on success.

Примеры

Пример 1. A json_encode() example

Результат выполнения данного примера:

Пример 2. A json_encode()
Пример 3. Эмулятор json_encode()
Пример 3. Сохранение русских букв(кирилицы) при использовании json_encode()

А вот пример кодирования сервером строки JSON при помощи стандартной функции в php "json_encode()" и добавочной к ней. В результате русские буковки остаются русскими. Начиная с версии PHP 5.4.0. можно воспользоваться стандартныой опцией JSON_UNESCAPED_UNICODE

Исходный объект в кодировке UTF-8.

Проблемы с которыми сталкиваются программисты

Доступ к полям

Проблема заключается в том что json_encode имеет доступ только к публичным полям объекта. Например если у вас есть класс

то результатом выполнения следующего кода будет:

как видно в результирующий json были включены только публичные поля.
Что же делать если нужны все поля?

Для php >= 5.4 достаточно будет реализовать интерфейс JsonSerializable для нашего класса, что подразумевает добавление метода jsonSerialize который будет возвращать структуру представляющую объект для json_encode

Теперь мы можем использовать json_encode как и раньше

Почему не стоит использовать подход с toJson методом?
Многие наверно заметили что подход с созданием метода возвращающего json может быть использован и в версиях php >= 5.4. Так почему же не воспользоваться им? Все дело в том что ваш класс может быть использован как часть иной структуры данных

и результат уже будет совсем другой. Также класс может использоваться другими программистами, для которых такой тип получение json-а с объекта может быть не совсем очевиден.

Что если у меня очень много полей в класcе?
В таком случае можно воспользоваться функцией get_object_vars

А если нужно private-поля, из класса, который нет возможности редактировать?
Может получиться ситуация когда нужно получить private поля (именно private, т.к. доступ к protected полям можно получить через наследование) в json-е. В таком случае необходимо будет воспользоваться рефлексией:

Кодировка текстовых значений

Кириллица и другие знаки в UTF8
Второй тип распространённых проблем с json_encode это проблемы с кодировкой. Часто текстовые значения которые нужно кодировать в json имеют в себе символы в UTF8 (в том числе кириллица) в результате эти символы будут представлены в виде кодов:

Отображение таких символов лечится очень просто — добавлением флага JSON_UNESCAPED_UNICODE вторым аргументом к функции json_encode:

Символы в других кодировках
Функция json_encode воспринимает строковые значения как строки в UTF8, что может вызвать ошибку, если кодировка другая. Рассмотрим маленький кусочек кода (данный пример кода максимально упрощен для демонстрации проблемной ситуации)

На первый взгляд ничего не предвещает проблем, да и что здесь может пойти не так? Я тоже так думал. В подавляющем большинстве случаев все будет работать, и по этой причине поиск проблемы занял у меня несколько больше времени, когда я впервые столкнулся с тем что результатом json_encode было false.

Для воссоздания такой ситуации предположим что p=%EF%F2%E8%F6%E0 (на пример: localhost?=%EF%F2%E8%F6%E0 ). *Переменные в суперглобальных массивах $_GET и $_REQUEST уже декодированы.

Как можно увидеть из ошибки: проблема с кодировкой переданной строки (это не UTF8). Решение проблемы очевидное — привести значение в UTF8

Цифровые значения

Последняя типовая ошибка связана с кодированием числовых значений.

Уже лучше. Но как видим «3.0» превратилось в 3, что в большинстве случаев будет интерпретировано как int. Используем еще один флаг JSON_PRESERVE_ZERO_FRACTION для корректного преобразования в float:

Прошу также обратить внимание на следующий фрагмент кода, что иллюстрирует ряд возможных проблем с json_encode и числовыми значениями:

Веб-разработчик клиента пожаловался, что json-файл, который я передаю ему на FTP Bitrix-сайта, приходит в кодировке UTF с BOM.

Я проверил, действительно Notepad++ определяет его в такой кодировке:


Это легко проверить если открыть файл в двоичном виде (в Total Commander):


Как видно, в начале файла содержится 3 байта EF BB BF. Это и есть BOM-кодировка.

Нашел решение на инфостарте поиском.


В решении используется функция ЗаписьТекста:


Заменил ТекстовыйДокумент на ЗаписьТекста:

Лок_ИмяФайла = КаталогВременныхФайлов () + Строка (Новый УникальныйИдентификатор );

ТекстСопутствующих = Обработки . дор_РассчетСопутствующихДляСайта . РассчитатьВФайл ();

УдалитьФайлы ( Лок_ИмяФайла ); //Не обязательно, у файла уникальное имя, но для общности
ЗаписьТекста = Новый ЗаписьТекста ( Лок_ИмяФайла , КодировкаТекста . UTF8 ,,Ложь, Символы . ПС );
//Т = Новый ТекстовыйДокумент();
ЗаписьТекста . Записать ( ТекстСопутствующих );
//Т.УстановитьТекст(ТекстСопутствующих);
//Т.Записать(Лок_ИмяФайла);
ЗаписьТекста . Закрыть ();

Поиском нашел этот файл в каталоге:


Но увы, независимо от значения параметра Дописывать, 1С настойчиво добавляло BOM-кодировку:


Бюджет решения не позволялся углубляться в поиски, поэтому я сделал решение через ADODB.Stream, которое было написано в той же статье:

Т = Новый ТекстовыйДокумент ();
Т . УстановитьТекст ( ТекстСопутствующих );
Т . Записать ( Лок_ИмяФайлаНач );

УбитьВОМ ( Лок_ИмяФайлаНач , Лок_ИмяФайла );

Наконец у меня получился чистый UTF, без BOM:


Потом почитал, что метод через ЗаписьТекста работает не на всех режимах совместимости.

У меня была УТ11, релиз платформы 8.3.16.1502, режим совместимости 8.3.14.

Читайте также: