C 資料序列化之MessagePack

2021-08-13 22:53:32 字數 3352 閱讀 9389

對於msgpack,官方是這樣解釋的:

messagepack  是乙個高效的二進位制序列化格式。它讓你像json一樣可以在各種語言之間交換資料。但是它比json更快、更小。小的整數會被編碼成乙個位元組,短的字串僅僅只需要比它的長度多一位元組的大小。

這裡,說了,msgpack有兩個優勢,更快(fast),更小(small).

想要了解這些優勢原因,我們當然得先知道msgpack在記憶體中是怎麼儲存的,

json資料應該已經算是很小了,沒有什麼冗餘的資料了,但msgpack是從哪些方面讓儲存占用記憶體更小的呢?

舉例:json

這個json長度為57位元組,但是為了表示這個資料結構(所有標紅色的地方就是他為了表示這個資料結構而不得不新增的),它用了23個位元組(就是那些大括號、引號、冒號之類的,他們是白白多出來的)。大家可以去 上看看json的資料標示定義。

換成messagepack,我只能給大家貼**和結果了,38位元組.

msg壓縮規則是什麼呢?

1.true、false 之類的:這些太簡單了,直接給1個位元組,(0xc2 表示true,0xc3表示false)

2.不用表示長度的:就是數字之類的,他們天然是定長的,是用乙個位元組表示後面的內容是什麼東東,比如用(0xcc 表示這後面,是個uint 8,用oxcd表示後面是個uint 16,用 0xca 表示後面的是個float 32).

3.不定長的:比如字串、陣列,型別後面加 1~4個位元組,用來存字串的長度,如果是字串長度是256以內的,只需要1個位元組,messagepack能存的最長的字串,是(2^32 -1 ) 最長的4g的字串大小。

4.ext結構:表示特定的小單元資料。

5.高階結構:map結構,就是key=>val 結構的資料,和陣列差不多,加1~4個位元組表示後面有多少個項。

這個是官方的資料表示結構文件:

總的來說,messagepack對數字、多位元組字元、陣列等都做了很多優化,減少了無用的字元,二進位制格式,也保證不用字元化帶來額外的儲存空間的增加,所以messagepack比json小是肯定的,小多少,得看你的資料。如果你用來存英文本串,那幾乎是沒有區別….

那麼,快又是從哪個方面快起來的呢?

先說說json怎麼解析吧,我們開發中一般都用cjson這個庫,cjson儲存的時候是採用鍊錶儲存的,其訪問方式很像一顆樹。每乙個節點可以有兄妹節點,通過next/prev指標來查詢,它類似雙向鍊錶;每個節點也可以有孩子節點,通過child指標來訪問,進入下一層。問題就是首先,構造這個鍊錶的時候,得乙個字元乙個字元地匹配過去吧,得判斷是不是引號、括號之類的吧…

但是messagepack 則簡單多了,直接一遍遍歷過去了,從前面的資料頭,就可以知道後面的是什麼資料,指標應該向後移動多少,比json的構建鍊錶少了很多比較的過程。

應用1:

using namespace msgpack;

using namespace std;

msgpack::sbuffer sbuf;

msgpack::packerpker(&sbuf);

// 序列化

pker.pack_map(3);

pker.pack(string("type"));

pker.pack(3);

pker.pack(string("ratio"));

pker.pack(2.15);

pker.pack(string("msg"));

pker.pack(string("hello world"));

int compresssize = sbuf.size();

// 反序列化

msgpack::v1::unpacked unpack;

msgpack::v1::unpack(&unpack, sbuf.data(), sbuf.size());

// 直接輸出結果

msgpack::object obj = unpack.get();

cout << obj << endl;

// 訪問具體鍵值對

msgpack::v2::object_kv* pkv;

msgpack::v2::object_kv* pkv_end;

msgpack::v2::object pk, pv;

if (obj.via.map.size > 0)

while (pkv < pkv_end);

}

應用2:(類的序列化)

類的序列化非常簡單,只需要類中新增一行巨集,就可以實現資料的序列化

#include #include #include #include class commandmsg ;

std::vectormy_class_vec;

commandmsg tempmsg;

tempmsg.m_mapname = "hello,dog";

tempmsg.m_map.insert(std::make_pair("aa1", 10));

tempmsg.m_map.insert(std::make_pair("aa2", 20));

my_class_vec.push_back(tempmsg);

commandmsg tempmsg2;

tempmsg2.m_mapname = "opengl";

tempmsg2.m_map.insert(std::make_pair("001", 1));

tempmsg2.m_map.insert(std::make_pair("002", 2));

tempmsg2.m_map.insert(std::make_pair("003", 3));

my_class_vec.push_back(tempmsg2);

// add some data

msgpack::v2::sbuffer buffer;

msgpack::v2::pack(buffer, my_class_vec);

msgpack::v1::unpacked msg;

msgpack::v1::unpack(&msg, buffer.data(), buffer.size());

msgpack::v1::object obj = msg.get();

std::vectormy_class_vec_r;

obj.convert(&my_class_vec_r);

for (int i = 0; i < my_class_vec.size(); i++)

}

C 資料序列化之MessagePack

對於msgpack,官方是這樣解釋的 messagepack 是乙個高效的二進位制序列化格式。它讓你像json一樣可以在各種語言之間交換資料。但是它比json更快 更小。小的整數會被編碼成乙個位元組,短的字串僅僅只需要比它的長度多一位元組的大小。這裡,說了,msgpack有兩個優勢,更快 fast ...

Django 序列化資料之單錶資料序列化

ret errors obj.errors.as data result json.dumps ret,cls jsoncustomencoder jsoncustomencoder是自定義的cls,用來轉換ret中特殊的error欄位型別 第一種 v的型別是未知的 from django.core...

C 序列化 反序列化

序列化又稱序列化,是.net執行時環境用來支援使用者定義型別的流化的機制。其目的是以某種儲存形成使自定義物件持久化,或者將這種物件從乙個地方傳輸到另乙個地方。net框架提供了兩種序列化的方式 1 是使用binaryformatter進行序列化 2 使用soapformatter進行序列化 3 使用x...