序列化庫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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM