Python json.dumps кортежа с некоторыми символами UTF-8 либо терпит неудачу, либо преобразует их. Я хочу, чтобы закодированный символ сохранялся как есть

На моем сервере скрипт Python получает данные из базы данных в виде кортежа. Затем сценарий преобразует кортеж в строку (с помощью json.dumps()) для передачи сценарию JavaScript в браузере пользователя.

Данные включают немецкие имена, такие как Вайдмюллер. Когда скрипт Python получает эти данные, он возвращает их как Weidm\xfcller, где \xfc — это кодировка UTF-8 для ü. Все идет нормально.

Однако,

  • json.dumps(tableData,ensure_ascii=False) преобразует \xfc в �
  • json.dumps(tableData,ensure_ascii=True) не удается: «UnicodeDecodeError: кодек 'utf8' не может декодировать байт 0xfc в позиции 5: неверный начальный байт»

Чего я действительно хочу, так это того, чтобы json.dumps оставил в покое символ в кодировке UTF-8; просто передать \xfc как есть. Таким образом, сценарий JavaScript в браузере пользователя сможет выполнить декодирование. Это возможно?

Или я неправильно подхожу к проблеме?

Вот полный код:

import MySQLdb

...


    # Open the data base and return a handle to it and its cursor
    dataBase, dbCursor = database.OpenDB()

    # Get data from the URL
    fieldStore = cgi.FieldStorage()
    selFieldName = selFieldValue = ''
    sqlQuery = 'SELECT * FROM %s' % (database.CompTableName)
    if ('fldName' in fieldStore) and ('fldValue' in fieldStore):
        fldName = fieldStore['fldName'].value
        fldValue = fieldStore['fldValue'].value
        sqlQuery += ' WHERE %s = \'%s\'' % (fldName,fldValue)
    if ('max' in fieldStore):
        maxRows = fieldStore['max'].value
        sqlQuery += ' LIMIT ' + maxRows
     # Get the selected data in the table as a list of lists 
    rowsAffected = dbCursor.execute(sqlQuery)
    tableData = dbCursor.fetchall()
    # Close the database and return the results
    dataBase.close()
    
    jsonTableData = json.dumps(tableData,encoding='latin1',ensure_ascii=True)
    print jsonTableData

И вот тестовый код:

    tableData = (('item1', 'Jones',), ('item2', 'Weidm\xfcller'))
    jsonTableData = json.dumps(tableData,encoding='latin1',ensure_ascii=True)
    print jsonTableData

Вы сбрасываете байты? У вас должен быть символ ü, а не \xfc в любой форме.

deceze 19.04.2024 19:59

«Вы сбрасываете байты‽» Я не знаю, что означает «сброс», извините. Вы имеете в виду "конвертировать"? "в любой форме" Это не форма, это база данных.

Davide Andrea 19.04.2024 20:01

Свалка = json.dumps

deceze 19.04.2024 20:05

Спасибо вам за разъяснение. Нет, я не «сбрасываю» байты. Я «сбрасываю» кортеж.

Davide Andrea 19.04.2024 20:06

И что именно содержит этот кортеж? Байты? Откуда они? Адаптер базы данных в идеале должен возвращать текст, str, тогда это не проблема.

deceze 19.04.2024 20:09

«И что именно содержит этот кортеж?» Пример: (('item1', 'Jones',), ('item2', 'Weidm\xfcller')). «Адаптер базы данных в идеале должен возвращать...» кортеж, включающий строки. sqlQuery = 'SELECT * FROM %s' % (database.TableName) ... dbCursor.execute(sqlQuery) ... tableData = dbCursor.fetchall() Возвращает кортеж.

Davide Andrea 19.04.2024 20:18

Что это за адаптер базы данных? И какая версия Python? Вы, наверное, используете Python 2? Пожалуйста, предоставьте минимально воспроизводимый пример.

deceze 19.04.2024 20:20

MySQLdb. Питон 2, да.

Davide Andrea 19.04.2024 20:25

@DavideAndrea Это недействительный JSON, если он не закодирован в UTF-8. Отредактируйте свой вопрос, используя воспроизводимый пример.

Mark Tolonen 19.04.2024 20:41

Если вы используете Python 2, 'Weidm\xfcller' является правильным и содержит escape-код для ü. print это правильно увидеть.

Mark Tolonen 19.04.2024 20:44

@Марк Толонен. TIL, что в строках JSON допускается только UTF-8. Спасибо. Теперь я рассмотрю этот вопрос в ином свете. «воспроизводимый пример» Трудно сделать, когда речь идет о доступе к базе данных: мне пришлось бы опубликовать учетные данные для входа. Я не могу так, извини.

Davide Andrea 19.04.2024 21:32

@Дэвид, нет, ты просто установил переменную с минимальным содержимым и покажи, как записать json в файл. БД не требуется

Mark Tolonen 20.04.2024 02:45
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
12
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

\xfc — это не кодировка UTF-8 для ü, это кодировка Latin-1.

>>> u'ü'.encode('latin-1')
'\xfc'
>>> u'ü'.encode('utf-8')
'\xc3\xbc'

Если вы json.dumps отправляете текст, вы не должны получать такие символы замены:

>>> json.dumps({u"k": u"Weidmüller"})
'{"k": "Weidm\\u00fcller"}'
>>> json.dumps({u"k": u"Weidmüller"}, ensure_ascii=False)
u'{"k": "Weidm\xfcller"}'

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

«это кодировка Latin-1» Спасибо. Это то, что мне было нужно. Я решил это с помощью json.dumps(tableData,encoding='latin1',ensure_ascii=True)

Davide Andrea 19.04.2024 20:33

@DavideAndrea Это недействительный JSON, если он не закодирован в UTF-8.

Mark Tolonen 19.04.2024 20:41

@DavideAndrea Это не то «решение», к которому я хотел, чтобы вы пришли из этого ответа. Вам следует убедиться, что ваши кортежи содержат элементы Юникода, а не элементы str. Это означает правильную настройку адаптера базы данных.

wim 19.04.2024 21:16

@wim Я пересмотрю свой подход, основываясь на твоем совете. Спасибо.

Davide Andrea 19.04.2024 21:33

Другие вопросы по теме