When looking at what characters are encoded by the hexadecimal strings, you can see that the first one decodes to
'\x81\xa7api_key\xd9 ad09739ac168ff2a199fb24eb4e24db8' # Python's version
while the second one decodes to
'\x81\xa7api_key\xda\x00 ad09739ac168ff2a199fb24eb4e24db8' # ObjC's version
The third, 30 bytes long string, decodes to
'\x81\xa7api_key\xbead09739ac168ff2a199fb24eb4e24d' # both versions
Intrigued by the problem, I googled for MsgPack's specs and came across this.
Now things are getting clearer.
\x81
says that the following is a one-element map.\xA7
says that the following is a seven-character string.api_key
is that seven-character string.
So far, so good. Now the differences begin:
\xd9
says that astr8
string follows. The byte after\xd9
is\x20
(hex 20 == dec 32 == ASCII space
). It denotes the length of that string (32). That's what Python uses, correctly, becausestr8
is usable for strings of up to 255 characters in length.\xda
says that astr16
string follows. The following two bytes are\x00\x20
(hex 0020
==dec 32
, as before). They also denote the length of the following string (32 again). That's what ObjC does, apparently. This is just as legal from the spec's point of view, just a little wasteful (one wasted byte).- For strings of less than 32 characters, both implementations use a
fixstr
type that encodes a length of 1-31 characters in the bitfield101xxxxx
which becomes\xbe
for a 30-character string (bin 10111110
).
So it seems that all the serializations are correct, but the deserializer you're using can't handle the str8
datatype used by Python's serializer. The implementation guidelines state that dut to format changes, not all releases support str8
, so that serializers should provide a compatibility mode without it. Python's msgpack
package doesn't, though.
UPDATE: Just a few hours after the bug report, the developer of msgpack-Python
has added a compatibility switch to force Python to create str16
serializations instead of str8
. Well done!