msgpack unserialising dict键字符串到字节

时间:2018-01-18 11:13:52

标签: python msgpack

我在python中遇到msgpack的问题。似乎在序列化dict时,如果键是字符串str,则它们不会被正确地反序列化并导致KeyError异常被引发。

示例:

>>> import msgpack
>>> d = dict()
>>> value = 1234
>>> d['key'] = value
>>> binary = msgpack.dumps(d)
>>> new_d = msgpack.loads(binary)
>>> new_d['key']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'key'

这是因为在调用loads()之后键不是字符串,而是反序列化为bytes个对象。

>>> d.keys()
dict_keys(['key'])
>>> new_d.keys()
dict_keys([b'key'])

这似乎与提到in github

的未实现功能有关

我的问题是,有没有办法解决这个问题或解决方法以确保在反序列化时可以使用相同的密钥?

我想使用msgpack但是如果我无法使用dict密钥构建str对象并期望能够在deserilisation上使用相同的密钥,那么它将变得毫无用处。 / p>

3 个答案:

答案 0 :(得分:6)

调用dumpspackb

时设置默认编码
:param str encoding:
 |      Convert unicode to bytes with this encoding. (default: 'utf-8')

但在调用loadsunpackb时默认设置

,如下所示:

Help on built-in function unpackb in module msgpack._unpacker:

unpackb(...)
    unpackb(... encoding=None, ... )

因此,更改反序列化的编码可以解决问题,例如:

>>> d['key'] = 1234
>>> binary = msgpack.dumps(d)
>>> msgpack.loads(binary, encoding = "utf-8")
{'key': 1234}
>>> msgpack.loads(binary, encoding = "utf-8") == d
True

答案 1 :(得分:2)

在您的示例中,使用raw=False这样的标志对我有用:

msgpack.unpackb(binary, raw=False)
# or
msgpack.loads(binary, raw=False)

请参见https://msgpack-python.readthedocs.io/en/latest/api.html#msgpack.Unpacker

raw(布尔)–如果为true,则将msgpack raw解压缩为Python字节。否则,通过使用UTF-8编码(默认)进行解码来解压缩到Python str。

答案 2 :(得分:0)

尝试以下方法:

def c_msgpackloads(bin):
    new_d = msgpack.loads(bin)
    new_d = {key.decode('utf-8') if isinstance(key, bytes) else key: new_d[key].decode('utf-8') if isinstance(new_d[key], bytes) else new_d[key] for key in new_d}
    return new_d

这是一个自定义加载函数,可以加载dict并自动将bytes键和值编码为utf-8字符串。