# MessagePack MessagePack is an efficient binary serialization format. It lets you exchange data among multiple languages like JSON. But it's faster and smaller. Small integers are encoded into a single byte, and typical short strings require only one extra byte in addition to the strings themselves. References - [MessagePack website](https://msgpack.org) - [MessagePack specification](https://github.com/msgpack/msgpack/blob/master/spec.md) ## Serialization The library uses the following mapping from JSON values types to MessagePack types according to the MessagePack specification: | JSON value type | value/range | MessagePack type | first byte | | --------------- | ---------------------------------------- | ---------------- | ---------- | | null | `null` | nil | 0xC0 | | boolean | `true` | true | 0xC3 | | boolean | `false` | false | 0xC2 | | number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3 | | number_integer | -2147483648..-32769 | int32 | 0xD2 | | number_integer | -32768..-129 | int16 | 0xD1 | | number_integer | -128..-33 | int8 | 0xD0 | | number_integer | -32..-1 | negative fixint | 0xE0..0xFF | | number_integer | 0..127 | positive fixint | 0x00..0x7F | | number_integer | 128..255 | uint 8 | 0xCC | | number_integer | 256..65535 | uint 16 | 0xCD | | number_integer | 65536..4294967295 | uint 32 | 0xCE | | number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF | | number_unsigned | 0..127 | positive fixint | 0x00..0x7F | | number_unsigned | 128..255 | uint 8 | 0xCC | | number_unsigned | 256..65535 | uint 16 | 0xCD | | number_unsigned | 65536..4294967295 | uint 32 | 0xCE | | number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF | | number_float | *any value representable by a float* | float 32 | 0xCA | | number_float | *any value NOT representable by a float* | float 64 | 0xCB | | string | *length*: 0..31 | fixstr | 0xA0..0xBF | | string | *length*: 32..255 | str 8 | 0xD9 | | string | *length*: 256..65535 | str 16 | 0xDA | | string | *length*: 65536..4294967295 | str 32 | 0xDB | | array | *size*: 0..15 | fixarray | 0x90..0x9F | | array | *size*: 16..65535 | array 16 | 0xDC | | array | *size*: 65536..4294967295 | array 32 | 0xDD | | object | *size*: 0..15 | fix map | 0x80..0x8F | | object | *size*: 16..65535 | map 16 | 0xDE | | object | *size*: 65536..4294967295 | map 32 | 0xDF | | binary | *size*: 0..255 | bin 8 | 0xC4 | | binary | *size*: 256..65535 | bin 16 | 0xC5 | | binary | *size*: 65536..4294967295 | bin 32 | 0xC6 | Complete mapping The mapping is **complete** in the sense that any JSON value type can be converted to a MessagePack value. Any MessagePack output created by `to_msgpack` can be successfully parsed by `from_msgpack`. Size constraints The following values can **not** be converted to a MessagePack value: - strings with more than 4294967295 bytes - byte strings with more than 4294967295 bytes - arrays with more than 4294967295 elements - objects with more than 4294967295 elements NaN/infinity handling If NaN or Infinity are stored inside a JSON number, they are serialized properly in contrast to the [dump](https://json.nlohmann.me/api/basic_json/dump/index.md) function which serializes NaN or Infinity to `null`. Example ``` #include #include #include using json = nlohmann::json; using namespace nlohmann::literals; int main() { // create a JSON value json j = R"({"compact": true, "schema": 0})"_json; // serialize it to MessagePack std::vector v = json::to_msgpack(j); // print the vector content for (auto& byte : v) { std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << (int)byte << " "; } std::cout << std::endl; } ``` Output: ``` 0x82 0xa7 0x63 0x6f 0x6d 0x70 0x61 0x63 0x74 0xc3 0xa6 0x73 0x63 0x68 0x65 0x6d 0x61 0x00 ``` ## Deserialization The library maps MessagePack types to JSON value types as follows: | MessagePack type | JSON value type | first byte | | ---------------- | --------------- | ---------- | | positive fixint | number_unsigned | 0x00..0x7F | | fixmap | object | 0x80..0x8F | | fixarray | array | 0x90..0x9F | | fixstr | string | 0xA0..0xBF | | nil | `null` | 0xC0 | | false | `false` | 0xC2 | | true | `true` | 0xC3 | | float 32 | number_float | 0xCA | | float 64 | number_float | 0xCB | | uint 8 | number_unsigned | 0xCC | | uint 16 | number_unsigned | 0xCD | | uint 32 | number_unsigned | 0xCE | | uint 64 | number_unsigned | 0xCF | | int 8 | number_integer | 0xD0 | | int 16 | number_integer | 0xD1 | | int 32 | number_integer | 0xD2 | | int 64 | number_integer | 0xD3 | | str 8 | string | 0xD9 | | str 16 | string | 0xDA | | str 32 | string | 0xDB | | array 16 | array | 0xDC | | array 32 | array | 0xDD | | map 16 | object | 0xDE | | map 32 | object | 0xDF | | bin 8 | binary | 0xC4 | | bin 16 | binary | 0xC5 | | bin 32 | binary | 0xC6 | | ext 8 | binary | 0xC7 | | ext 16 | binary | 0xC8 | | ext 32 | binary | 0xC9 | | fixext 1 | binary | 0xD4 | | fixext 2 | binary | 0xD5 | | fixext 4 | binary | 0xD6 | | fixext 8 | binary | 0xD7 | | fixext 16 | binary | 0xD8 | | negative fixint | number_integer | 0xE0-0xFF | Info Any MessagePack output created by `to_msgpack` can be successfully parsed by `from_msgpack`. Example ``` #include #include #include using json = nlohmann::json; int main() { // create byte vector std::vector v = {0x82, 0xa7, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xc3, 0xa6, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00 }; // deserialize it with MessagePack json j = json::from_msgpack(v); // print the deserialized JSON value std::cout << std::setw(2) << j << std::endl; } ``` Output: ``` { "compact": true, "schema": 0 } ```