我正在使用MessagePack开发客户端SDK。我需要在java,ObjC和python中开发客户端,而我的服务器是在java中。我对java和ObjC msgpack库没有任何问题,但是在python中,当我打包一个字符串值大于31个字符的字典时,打包数据不会在其他语言中解压缩。尝试在python中解压缩相同的工作正常,只要字符串长度小于32,互操作性也非常好。以下是一个失败的python示例..
myPacket = {u"api_key":u"ad09739ac168ff2a199fb24eb4e24db8"}
msgPackedPacket = umsgpack.packb(myPacket)
为此生成的二进制数据是
<81a76170 695f6b65 79d92061 64303937 33396163 31363866 66326131 39396662 32346562 34653234 646238>
如果我在ObjC中隐藏具有相同键值的字典,我会得到
<81a76170 695f6b65 79da0020 61643039 37333961 63313638 66663261 31393966 62323465 62346532 34646238>
ObjC结果解包很好而python不会..你可以注意到来自ObjC的数据中的2个额外字节。
如下正确运作的例子
myPacket = {u"api_key":u"ad09739ac168ff2a199fb24eb4e24d"}
字符数= 30这里..我在python中得到以下字节
<81a76170 695f6b65 79be6164 30393733 39616331 36386666 32613139 39666232 34656234 65323464>
对于ObjC,我得到以下字节..
<81a76170 695f6b65 79be6164 30393733 39616331 36386666 32613139 39666232 34656234 65323464>
如果我错过了一些显而易见的事情,我很抱歉..寻找任何变通办法或建议,因为我被打了一天以上..
提前致谢。
答案 0 :(得分:3)
当查看由十六进制字符串编码的字符时,您可以看到第一个字符解码为
'\x81\xa7api_key\xd9 ad09739ac168ff2a199fb24eb4e24db8' # Python's version
而第二个解码为
'\x81\xa7api_key\xda\x00 ad09739ac168ff2a199fb24eb4e24db8' # ObjC's version
第三个30字节长的字符串,解码为
'\x81\xa7api_key\xbead09739ac168ff2a199fb24eb4e24d' # both versions
对这个问题感兴趣,我用Google搜索了MsgPack的规格并遇到了this。
现在事情越来越清晰。
\x81
表示以下是单元素地图。\xA7
表示以下是七个字符的字符串。api_key
是七个字符的字符串。 到目前为止,这么好。现在差异开始了:
\xd9
表示后跟一个str8
字符串。 \xd9
之后的字节为\x20
(hex 20 == dec 32 == ASCII space
)。它表示该字符串的长度(32)。这正是Python正确使用的原因,因为str8
可用于长度不超过255个字符的字符串。\xda
表示后跟一个str16
字符串。以下两个字节为\x00\x20
(hex 0020
== dec 32
,与之前一样)。它们还表示后续字符串的长度(再次为32)。这显然是ObjC所做的。从规范的角度来看,这也是合法的,只是有点浪费(一个浪费的字节)。fixstr
类型,该字段在位域101xxxxx
中编码长度为1-31个字符,对于30个字符变为\xbe
字符串(bin 10111110
)。 所以看起来所有序列化都是正确的,但是你使用的解串器无法处理Python序列化器使用的str8
数据类型。用于格式化更改的implementation guidelines状态,并非所有版本都支持str8
,因此序列化程序应提供不带它的兼容模式。但是,Python的msgpack
包不会。
更新:bug report后几个小时,msgpack-Python
的开发人员添加了一个兼容性开关,强制Python创建str16
序列化,而不是str8
。做得好!