MsgPack简介
MsgPack 是一个序列化库,可以将对象序列化为二进制数据,也可以将二进制数据反序列化为对象。
与其他数据序列化格式(如JSON和XML)相比,MsgPack 具有更高的性能和更小的序列化大小。它的序列化和反序列化过程非常快速,并且生成的二进制数据体积小,节省带宽和存储空间。
MsgPack 提供了多种语言的实现,包括但不限于 C/C++、Java、Python、JavaScript、Ruby、Go、C#、PHP 等,使得不同语言的应用程序可以方便地进行数据交换和通信。
MsgPack 的官方网站:https://msgpack.org/
官网简单示例
#include <msgpack.hpp>
#include <vector>
#include <string>
#include <iostream>
int main(void) {
// serializes this object.
std::vector<std::string> vec;
vec.push_back("Hello");
vec.push_back("MessagePack");
// serialize it into simple buffer.
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, vec);
// deserialize it.
msgpack::object_handle oh =
msgpack::unpack(sbuf.data(), sbuf.size());
// print the deserialized object.
msgpack::object obj = oh.get();
std::cout << obj << std::endl; //=> ["Hello", "MessagePack"]
// convert it into statically typed object.
std::vector<std::string> rvec;
obj.convert(rvec);
}
编译并输出:
$ g++ -Ipath_to_msgpack/include hello.cc -o hello
$ ./hello
["Hello", "MessagePack"]
流式序列化
#include <msgpack.hpp>
#include <iostream>
#include <string>
int main() {
// serializes multiple objects using msgpack::packer.
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"));
// deserializes these objects using msgpack::unpacker.
msgpack::unpacker pac;
// feeds the buffer.
pac.reserve_buffer(buffer.size());
memcpy(pac.buffer(), buffer.data(), buffer.size());
pac.buffer_consumed(buffer.size());
// now starts streaming deserialization.
msgpack::object_handle oh;
while(pac.next(oh)) {
std::cout << oh.get() << std::endl;
}
// results:
// $ g++ -Ipath_to_msgpack/include stream.cc -o stream
// $ ./stream
// "Log message ... 1"
// "Log message ... 2"
// "Log message ... 3"
}
序列化 array
与 map
#include <msgpack.hpp>
#include <iostream>
#include <string>
int main() {
// serializes multiple objects into one message containing an array using msgpack::packer.
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"));
// serializes multiple objects into one message containing a map using msgpack::packer.
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);
}
序列化自定义类型
#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;
// add some elements into vec...
// you can serialize myclass directly
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, vec);
msgpack::object_handle oh =
msgpack::unpack(sbuf.data(), sbuf.size());
msgpack::object obj = oh.get();
// you can convert object to myclass directly
std::vector<myclass> rvec;
obj.convert(rvec);
}
封装序列化函数
继承的方式
#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 定义序列化和反序列化的字段
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;
}
使用更加复杂的类进行序列化
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 定义序列化和反序列化的字段
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
宏定义的下面添加如下两个函数,即可拥有序列化和反序列化的功能。
#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); \
}