序列化库MessagePack应用(C++)

介绍

MessagePack(简称msgpack)是一个小巧而高效的序列化/反序列化库,支持多种开发语言。官方网站:http://msgpack.org/

下面是官方的一个简介:

It's like JSON.
but fast and small.

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.

msgpack支持非常多的开发语言,这篇随笔只讨论在C++代码中的调用。

序列化键值对数据

一个经常遇到的应用场景是,我们需要序列化一组键值对。这组键值对的大小是可变的,值类型也不确定,例如:

key name  key type value type
type string int
ratio string double
msg string string

示例代码如下:

 1 /*
 2  * msgpack C++试验:序列化/反序列化大小可变的非标准map.
 3  * Author: 赵子清
 4  * Blog: http://www.cnblogs.com/zzqcn
 5  *
 6  * */
 7 
 8 
 9 #include <msgpack.hpp>
10 #include <string>
11 #include <cstring>
12 #include <iostream>
13 using namespace std;
14 
15 int main(int argc, char** argv)
16 {
17 
18     msgpack::sbuffer  sbuf;
19     msgpack::packer<msgpack::sbuffer>   pker(&sbuf);
20 
21     // 序列化
22     pker.pack_map(3);
23     pker.pack(string("type"));
24     pker.pack(3);
25     pker.pack(string("ratio"));
26     pker.pack(2.15);
27     pker.pack(string("msg"));
28     pker.pack(string("hello world"));
29 
30     // 反序列化
31     msgpack::unpacked  unpack;
32     msgpack::unpack(&unpack, sbuf.data(), sbuf.size());
33 
34     // 直接输出结果
35     msgpack::object  obj = unpack.get();
36     cout << obj << endl;
37 
38     // 访问具体键值对
39     msgpack::object_kv*  pkv;
40     msgpack::object_kv*  pkv_end;
41     msgpack::object      pk, pv;
42     if(obj.via.map.size > 0)
43     {
44         pkv = obj.via.map.ptr;
45         pkv_end = obj.via.map.ptr + obj.via.map.size;
46 
47         do
48         {
49             pk = pkv->key;
50             pv = pkv->val;
51             
52             cout << pk << ", " << pv << endl;
53 
54             ++pkv;
55         }
56         while (pkv < pkv_end);
57     }
58 
59     return 0;
60 }

输出结果:

{"type"=>3, "ratio"=>2.15, "msg"=>"hello world"}
"type", 3
"ratio", 2.15
"msg", "hello world"


 

序列化自定义类型

msgpack已支持了很多的标准类型,但有时我们会自己定义新的类型,这时,我们必须对新类型做某些修改,以使msgpack可以操作它。

另外,如果你的类型中含有低层指针,则还需要进行一些处理,否则,msgpack只会进行浅拷贝,无法序列化指针所指向的内存数据。

假设我们原本的类型如下:

struct Foo
{
    int  i;
    string  str;
    char*  data;
};

那么要让msgpack操作它,应修改为如下结构:

struct Foo
{
    int     i;
    string  str;
    // 原始指针类型,内部封装了pack_raw和pack_raw_body方法
    msgpack::type::raw_ref  data;

    MSGPACK_DEFINE(i, str, data); 
};


下面是完整示例代码:

 1 /*
 2  * msgpack C++试验:序列化/反序列化自定义数据结构.
 3  * Author: 赵子清
 4  * Blog: http://www.cnblogs.com/zzqcn
 5  * */
 6 
 7 
 8 #include <msgpack.hpp>
 9 #include <string>
10 #include <cstring>
11 #include <iostream>
12 using namespace std;
13 
14 
15 struct Foo
16 {
17     int     i;
18     string  str;
19     // 原始指针类型,内部封装了pack_raw和pack_raw_body方法
20     msgpack::type::raw_ref  data;
21 
22     MSGPACK_DEFINE(i, str, data); 
23 };
24 
25 
26 int main(int argc, char** argv)
27 {
28     Foo  f;
29     f.i = 4;
30     f.str = "hello world";
31     const char* tmp = "msgpack";
32     f.data.ptr = tmp;
33     f.data.size = strlen(tmp) + 1;
34 
35     msgpack::sbuffer  sbuf;
36     msgpack::pack(sbuf, f);
37 
38     msgpack::unpacked  unpack;
39     msgpack::unpack(&unpack, sbuf.data(), sbuf.size());
40 
41     msgpack::object  obj = unpack.get();
42 
43     Foo f2;
44     obj.convert(&f2);
45 
46     cout << f2.i << ", " << f2.str << ", ";
47     cout << f2.data.ptr << endl;
48 
49     return 0;
50 }

 输出结果:

4, hello world, msgpack
原文地址:https://www.cnblogs.com/zzqcn/p/3562512.html