0%

MsgPack简介

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) {
// 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);
}

编译并输出:

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() {
// 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"
}

序列化 arraymap

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() {
// 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);

}

序列化自定义类型

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;
// 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);
}

封装序列化函数

继承的方式

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 定义序列化和反序列化的字段
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 定义序列化和反序列化的字段
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); \
}