Декодировать кодировку UTF-8 в строку JSON - PullRequest
0 голосов
/ 26 мая 2018

У меня есть файл JSON, который содержит следующие закодированные строки:

"sender_name": "Horn\u00c3\u00adkov\u00c3\u00a1",

Я пытаюсь проанализировать этот файл с помощью модуля json.Однако я не могу правильно декодировать эту строку.

Что я получаю после декодирования JSON с использованием метода .load(), это 'HornÃ\xadková'.Вместо этого строка должна быть правильно декодирована как 'Horníková'.

Я прочитал спецификацию JSON и понимаю, что после \u должно быть 4 шестнадцатеричных числа, указывающих номер Unicode символа.Но похоже, что в этом файле JSON байты в кодировке UTF-8 хранятся как \u -последовательности.

Какой это тип кодирования и как правильно его анализировать в Python 3?

Является ли этот тип файла JSON допустимым файлом JSON в соответствии со спецификацией?

Ответы [ 4 ]

0 голосов
/ 27 мая 2018

JSON, который вы читаете, был написан неправильно, и строки Unicode, декодированные из него, должны быть перекодированы с использованием неверной кодировки, а затем декодированы с правильной кодировкой.

Вот пример:

#!python3
import json

# The bad JSON you have
bad_json = r'{"sender_name": "Horn\u00c3\u00adkov\u00c3\u00a1"}'
print('bad_json =',bad_json)

# The wanted result from json.loads()
wanted = {'sender_name':'Horníková'}

# What correctly written JSON should look like
good_json = json.dumps(wanted)
print('good_json =',good_json)

# What you get when loading the bad JSON.
got = json.loads(bad_json)
print('wanted =',wanted)
print('got =',got)

# How to correct the mojibake string
corrected_sender = got['sender_name'].encode('latin1').decode('utf8')
print('corrected_sender =',corrected_sender)

Вывод:

bad_json = {"sender_name": "Horn\u00c3\u00adkov\u00c3\u00a1"}
good_json = {"sender_name": "Horn\u00edkov\u00e1"}
wanted = {'sender_name': 'Horníková'}
got = {'sender_name': 'HornÃ\xadková'}
corrected_sender = Horníková
0 голосов
/ 26 мая 2018

Ваш текст уже закодирован, и вам нужно сообщить об этом Python, используя префикс b в вашей строке, но поскольку вы используете json, а ввод должен быть строкой, вам придется декодировать закодированный текст вручную.Поскольку ваш ввод не является байтовым, вы можете использовать кодировку 'raw_unicode_escape', чтобы преобразовать строку в байт без кодирования и запретить методу open использовать собственную кодировку по умолчанию.Тогда вы можете просто использовать вышеупомянутый подход, чтобы получить желаемый результат.

Обратите внимание, что, поскольку вам необходимо выполнить кодирование и декодирование, вам необходимо прочитать содержимое файла и выполнить кодирование для загруженной строки, тогда вы должны использовать * 1006.*json.loads() вместо json.load().

In [168]: with open('test.json', encoding='raw_unicode_escape') as f:
     ...:     d = json.loads(f.read().encode('raw_unicode_escape').decode())
     ...:     

In [169]: d
Out[169]: {'sender_name': 'Horníková'}
0 голосов
/ 26 мая 2018

Перекодировать в байты, а затем перекодировать в текст.

>>> 'HornÃ\xadková'.encode('latin-1').decode('utf-8')
'Horníková'

Является ли файл JSON этого типа даже допустимым файлом JSON в соответствии со спецификацией?

Нет.

A строка - это последовательность из нуля или более символов Юникода , заключенные в двойные кавычки, с использованием экранирования обратной косой черты [выделение текста добавлено] .

источник

Строка - это последовательность кодовых точек Unicode , заключенная в кавычки (U + 0022).[...] Любая кодовая точка может быть представлена ​​в виде шестнадцатеричной escape-последовательности [...], представленной в виде шестизначной последовательности: обратный солидус, за которым следует строчная буква u, за которой следуют четыре шестнадцатеричные цифры, кодирующие кодовую точку. [выделение добавлено] .

source

Последовательности байтов UTF-8 не являются ни символами Unicode, ни кодовыми точками Unicode.

0 голосов
/ 26 мая 2018

Я не знаю достаточно о JSON, чтобы сказать, действительно ли это верно или нет, но вы можете проанализировать эти строки, используя raw_unicode_escape кодек:

>>> "Horn\u00c3\u00adkov\u00c3\u00a1".encode('raw_unicode_escape').decode('utf8')
'Horníková'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...