介绍
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 }
输出结果:
{"x"=>3, "y"=>2.15,
"z"=>"hello"} "x", 3 "y", 2.15 "z", "hello" |
序列化自定义类型
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 |