介紹
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 |