msgpack 将 dict 键字符串反序列化为字节
msgpack unserialising dict key strings to bytes
我在 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
但是如果我不能用 str
键构建一个 dict
对象并且期望能够在反序列化时使用相同的键,它就变得毫无用处.
尝试以下操作:
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
这是一个自定义加载函数,加载字典并自动将 bytes
键和值编码为 utf-8 字符串。
调用 dumps
或 packb
时设置了默认编码
:param str encoding:
| Convert unicode to bytes with this encoding. (default: 'utf-8')
但在调用 loads
或 unpackb
时默认设置为 而不是 ,如下所示:
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
在你的示例中使用 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 (bool) – If true, unpack msgpack raw to Python bytes. Otherwise, unpack to Python str by decoding with UTF-8 encoding (default).
我在 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
但是如果我不能用 str
键构建一个 dict
对象并且期望能够在反序列化时使用相同的键,它就变得毫无用处.
尝试以下操作:
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
这是一个自定义加载函数,加载字典并自动将 bytes
键和值编码为 utf-8 字符串。
调用 dumps
或 packb
时设置了默认编码
:param str encoding:
| Convert unicode to bytes with this encoding. (default: 'utf-8')
但在调用 loads
或 unpackb
时默认设置为 而不是 ,如下所示:
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
在你的示例中使用 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 (bool) – If true, unpack msgpack raw to Python bytes. Otherwise, unpack to Python str by decoding with UTF-8 encoding (default).