10

我正在尝试将包含非 ascii 字符的传入字节字符串转换为有效的 utf-8 字符串,以便我可以将其转储为 json。

b = '\x80'
u8 = b.encode('utf-8')
j = json.dumps(u8)

我希望 j 是 '\xc2\x80' 但我得到:

UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128)

在我的情况下,'b' 来自 mysql 通过 google 协议缓冲区,并填充了一些 blob 数据。

有任何想法吗?

编辑:我有以太网帧作为 blob 存储在 mysql 表中(请大家保持话题,不要讨论为什么表中有数据包)。表排序规则是 utf-8,db 层(sqlalchemy,非 orm)正在抓取数据并创建将 blob 存储为 python 'str' 的结构(google 协议缓冲区)。在某些情况下,我直接使用协议缓冲区没有任何问题。在其他情况下,我需要通过 json 公开相同的数据。我注意到的是,当 json.dumps() 做它的事情时,'\x80' 可以替换为无效的 unicode char (\ufffd iirc)

4

3 回答 3

9

您需要检查您正在使用的软件 API 的文档。BLOB 是首字母缩略词:BINARY大对象。

如果您的数据实际上是二进制的,那么将其解码为 Unicode 的想法当然是无稽之谈。

如果它实际上是文本,您需要知道使用什么编码将其解码为 Unicode。

然后您使用json.dumps(a_Python_object)... 如果您自己将其编码为 UTF-8,json则会再次将其解码:

>>> import json
>>> json.dumps(u"\u0100\u0404")
'"\\u0100\\u0404"'
>>> json.dumps(u"\u0100\u0404".encode('utf8'))
'"\\u0100\\u0404"'
>>>

更新latin1

u'\x80'是一个无用的无意义的 C1 控制字符——编码极不可能是 Latin-1。Latin-1 是“陷阱和妄想”——所有 8 位字节都被解码为 Unicode,而不会引发异常。不要混淆“有效”和“不会引发异常”。

于 2012-03-07T16:07:20.607 回答
6

用于b.decode('name of source encoding')获取 unicode 版本。当我学会它时,这让我很惊讶。例如:

In [123]: 'foo'.decode('latin-1')
Out[123]: u'foo'
于 2012-03-07T15:57:29.960 回答
2

我认为您要做的是解码某些编码的字符串对象。你知道那个编码是什么吗?获取 unicode 对象。

unicode_b = b.decode('some_encoding')

然后使用 utf_8 编码将 unicode 对象重新编码回字符串对象。

b = unicode_b.encode('utf_8')

使用 unicode 对象作为翻译器,在不知道字符串的原始编码是什么的情况下,我无法确定,但转换可能不会按预期进行。unicode 对象并不意味着将一种编码的字符串转换为另一种编码。假设您知道编码是什么,我将使用 unicode 对象,如果您不知道编码是什么,那么真的没有办法在没有反复试验的情况下找出答案,然后在何时转换回编码字符串你想要一个字符串对象回来。

于 2012-03-07T16:10:15.430 回答