0

In JavaScript, I can use msgpack to pack an object as follows:

msgpack.pack(payload);

Where payload is the following object:

var payload = { event: "phx_join", payload: {}, ref: "1", topic: "players:1" };

When I call msgpack.pack(payload); on this object, I get the following bytes back (as a Uint8Array):

[132, 165, 116, 111, 112, 105, 99, 169, 112, 108, 97, 121, 101, 114, 115, 58, 49, 165, 101, 118, 101, 110, 116, 168, 112, 104, 120, 95, 106, 111, 105, 110, 167, 112, 97, 121, 108, 111, 97, 100, 128, 163, 114, 101, 102, 161, 49]

How can I use msgpack-cli in C# to convert an object from C# to the same byte sequence as above? The object format I am using in C# is not so important, what's important is that the byte sequence is the same. Here is what I've tried:

public class Payload
{
    public string @event;
    public MessagePackObject payload;
    public string @ref;
    public string topic;
}

var payload = new Payload
{
    @event = "phx_join",
    payload = new MessagePackObject(),
    @ref = "1",
    topic = "players:1"
};
var packedBytes = SerializationContext.Default.GetSerializer<Payload>().PackSingleObject(payload);

Unfortunately, the packed bytes I get back in this case are as follows:

[148, 168, 112, 104, 120, 95, 106, 111, 105, 110, 192, 161, 49, 169, 112, 108, 97, 121, 101, 114, 115, 58, 49]

It is not the same as the packed data I get from JavaScript. I thought message pack was supposed to be cross-platform friendly. What's going on here and how can I create a C# equivalent object to make the deserializer pack it to the same byte array as it does in JavaScript?

Alexandru
  • 12,264
  • 17
  • 113
  • 208

1 Answers1

1

I figured it out. The trick is to check the first byte encoded in the JavaScript, and you will see that 132 corresponds to HEX 0x84. HEX 0x84 according to the message pack specification is a fixmap (0x80 to 0x8f). Using this hint, we can try to guess that a fixmap must correspond to a dictionary data type in C# (since a map is more or less like a dictionary of key-value pairs).

We just need to use a payload object that is actually a dictionary of string and object pairs, and msgpack-cli will successfully pack it to the same byte sequence from C#:

var payload = new Dictionary<string, object>() {
    { "event", "phx_join" },
    { "payload", new Dictionary<string, object>() },
    { "ref", "1" },
    { "topic", "players:1" }
};
var packedBytes = SerializationContext.Default.GetSerializer<Dictionary<string, object>>().PackSingleObject(payload);
Alexandru
  • 12,264
  • 17
  • 113
  • 208