Каков правильный способ сжатия и распаковки данных UTF-8 с помощью zlib?

У меня очень длинное сообщение JSON, содержащее символы, выходящие за пределы таблицы ASCII. Я конвертирую его в строку следующим образом:

messStr = json.dumps(message,encoding='utf-8', ensure_ascii=False, sort_keys=True) 

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

 ss = mStr[start:fin] # get piece of length X ssc = zlib.compress(ss) # compress it 

Когда я это сделаю, я получаю следующую ошибку от zlib.compress :

 UnicodeEncodeError: 'ascii' codec can't encode character u'\xf1' in position 225: ordinal not in range(128) 

Каков правильный способ сжимать строку UTF-8 и как правильно ее декомпрессировать?

Данные JSON не кодируются в кодировке UTF-8. Параметр encoding для функции json.dumps() указывает на то, как интерпретировать строки байтов Python в message (например, на входе), а не как кодировать полученный результат . Он не кодирует вывод вообще, потому что вы использовали ensure_ascii=False .

Кодировать данные перед сжатием:

 ssc = zlib.compress(ss.encode('utf8')) 

При распаковке снова нет необходимости декодировать из UTF-8; json.loads() предполагает UTF-8, если вход является байтовой.

Небольшое дополнение к ответу Мартинна. Я читал в блоге Enthoughtt замечательный один оператор линейки, который избавит вас от необходимости импортировать zlib в свой собственный код.

Безопасное сжатие строки (включая ваш json dump) будет выглядеть так:

 ssc = ss.encode('utf-8').encode('zlib_codec') 

Декомпрессия назад к utf-8 будет:

 ss = ssc.decode('zlib_codec').decode('utf-8') 

Надеюсь это поможет.