MsgPack 是一个序列化库,可以将对象序列化为二进制数据,也可以将二进制数据反序列化为对象。
与其他数据序列化格式(如JSON和XML)相比,MsgPack 具有更高的性能和更小的序列化大小。它的序列化和反序列化过程非常快速,并且生成的二进制数据体积小,节省带宽和存储空间。
MsgPack 提供了多种语言的实现,包括但不限于 C/C++、Java、Python、JavaScript、Ruby、Go、C#、PHP 等,使得不同语言的应用程序可以方便地进行数据交换和通信。
MsgPack 的官方网站:https://msgpack.org/
MsgPack C++ 版本开源代码库
官网简单示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <msgpack.hpp> #include <vector> #include <string> #include <iostream>
int main(void) { std::vector<std::string> vec; vec.push_back("Hello"); vec.push_back("MessagePack");
msgpack::sbuffer sbuf; msgpack::pack(sbuf, vec);
msgpack::object_handle oh = msgpack::unpack(sbuf.data(), sbuf.size());
msgpack::object obj = oh.get(); std::cout << obj << std::endl;
std::vector<std::string> rvec; obj.convert(rvec); }
|
编译并输出:
1 2 3
| $ g++ -Ipath_to_msgpack/include hello.cc -o hello $ ./hello ["Hello", "MessagePack"]
|
流式序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <msgpack.hpp> #include <iostream> #include <string>
int main() { msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer); pk.pack(std::string("Log message ... 1")); pk.pack(std::string("Log message ... 2")); pk.pack(std::string("Log message ... 3"));
msgpack::unpacker pac;
pac.reserve_buffer(buffer.size()); memcpy(pac.buffer(), buffer.data(), buffer.size()); pac.buffer_consumed(buffer.size());
msgpack::object_handle oh; while(pac.next(oh)) { std::cout << oh.get() << std::endl; }
}
|
序列化 array
与 map
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include <msgpack.hpp> #include <iostream> #include <string>
int main() { msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer); pk.pack_array(3); pk.pack(std::string("Log message ... 1")); pk.pack(std::string("Log message ... 2")); pk.pack(std::string("Log message ... 3"));
msgpack::sbuffer buffer2;
msgpack::packer<msgpack::sbuffer> pk2(&buffer2); pk2.pack_map(2); pk2.pack(std::string("x")); pk2.pack(3); pk2.pack(std::string("y")); pk2.pack(3.4321);
}
|
序列化自定义类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #include <msgpack.hpp> #include <vector> #include <string>
class myclass { private: std::string m_str; std::vector<int> m_vec; public: MSGPACK_DEFINE(m_str, m_vec); };
int main() { std::vector<myclass> vec;
msgpack::sbuffer sbuf; msgpack::pack(sbuf, vec);
msgpack::object_handle oh = msgpack::unpack(sbuf.data(), sbuf.size());
msgpack::object obj = oh.get();
std::vector<myclass> rvec; obj.convert(rvec); }
|
封装序列化函数
继承的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| #include <msgpack.hpp> #include <vector> #include <iostream> #include <string> #include <random>
int GetRandomInt(int min = 0, int max = 1000000) { static std::random_device rd; static std::mt19937 gen(rd()); static std::uniform_int_distribution<> dis(min, max); return dis(gen); }
std::string GetRandomString(size_t len = 10) { static std::random_device rd; static std::mt19937 gen(rd()); static std::uniform_int_distribution<> dis(0, 25);
std::string str; for (int i = 0; i < len; ++i) { str.push_back('a' + dis(gen)); }
return str; }
template <typename T> class MsgPackSerialization { public: virtual ~MsgPackSerialization() = default; bool operator==(const MsgPackSerialization&) const = default;
std::vector<char> Serialization() { msgpack::sbuffer sbuf; msgpack::pack(sbuf, *(static_cast<T*>(this))); std::vector<char> vec(sbuf.data(), sbuf.data() + sbuf.size()); return vec; }
void Deserialization(const std::vector<char>& vec) { msgpack::object_handle oh = msgpack::unpack(vec.data(), vec.size()); msgpack::object obj = oh.get(); obj.convert(*(static_cast<T*>(this))); } };
class myclass : public MsgPackSerialization<myclass> { public: bool operator==(const myclass&) const = default; myclass& operator=(const myclass& rhs) { if (this != &rhs) { m_str = rhs.m_str; m_vec = rhs.m_vec; } return *this; }
static myclass GetRandomObj() { myclass obj; obj.m_str = GetRandomString(10); auto num = GetRandomInt(0, 10); for (int i = 0; i < num; ++i) { obj.m_vec.push_back(GetRandomInt(0, 1000)); }
return obj; }
public: MSGPACK_DEFINE(m_str, m_vec);
private: std::string m_str; std::vector<int> m_vec; };
int main() { auto obj = myclass::GetRandomObj(); decltype(obj) obj2; auto vec = obj.Serialization(); obj2.Deserialization(vec);
if (obj2 == obj) { std::cout << "obj2 == obj" << std::endl; } else { std::cout << "obj2 != obj" << std::endl; }
return 0; }
|
使用更加复杂的类进行序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| class myclass2 : public MsgPackSerialization<myclass2> { public: bool operator==(const myclass2&) const { return m_str == m_str && m_vec == m_vec && m_class == m_class && m_vec_class == m_vec_class; }
static myclass2 GetRandomObj() { myclass2 obj; obj.m_str = GetRandomString(10); auto num = GetRandomInt(0, 10);
for (int i = 0; i < num; ++i) { obj.m_vec.push_back(GetRandomInt(0, 1000)); obj.m_vec_class.push_back(myclass::GetRandomObj()); }
obj.m_class = myclass::GetRandomObj();
return obj; }
public: MSGPACK_DEFINE(m_str, m_vec, m_class, m_vec_class);
private: std::string m_str; std::vector<int> m_vec; myclass m_class; std::vector<myclass> m_vec_class; };
int main() { auto obj = myclass2::GetRandomObj(); decltype(obj) obj2; auto vec = obj.Serialization(); obj2.Deserialization(vec);
if (obj2 == obj) { std::cout << "obj2 == obj" << std::endl; } else { std::cout << "obj2 != obj" << std::endl; }
return 0; }
|
组合的方式
在 MSGPACK_DEFINE
宏定义的下面添加如下两个函数,即可拥有序列化和反序列化的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13
| #define MSGPACK_DEFINE(...) ...\ std::shared_ptr<std::vector<char>> Serialization() \ { \ msgpack::sbuffer sbuf; \ msgpack::pack(sbuf, *this); \ return std::make_shared<std::vector<char>>(sbuf.data(), sbuf.data() + sbuf.size()); \ } \ void Deserialization(const std::shared_ptr<std::vector<char>>& vec) \ { \ msgpack::object_handle oh = msgpack::unpack(vec->data(), vec->size()); \ msgpack::object obj = oh.get(); \ obj.convert(*this); \ }
|