最近在做一些 IPC 通訊的研究,需要一個輕薄短小的序列化方式,因為 BinaryFormatter 已經被微軟宣布淘汰,因此選了幾個方式,MessagePack 是其中一個候選人,就順帶寫寫筆記。
在微軟的文件裡針對二進位序列化的替代有兩個建議選項 (1) MessagPack (2) protobuf-net ,先來研究一下 MessagePack,順便做點筆記。
MessagePack 的基本使用方式倒是挺簡單的,首先,當然是先用 Nuget 加入相關的 packages,寫文章當下的最新版本是 3.1.1,而且也支援 .NET Framework:
基本使用方式
基本使用非常簡單,就是加上必要的 Attribute 就行,例如:
[MessagePackObject]
public class Person
{
[Key(0)]
public string Name { get; set; }
[Key(1)]
public int Age { get; set; }
}
類別加上 MessagePackObjectAttribute ,屬性加上 KeyAttribute 賦予其具有整數型態的序列化鍵值。
如果覺得老是要加 KeyAttribute 很麻煩,另外一種方式是採用屬性名稱當作鍵值:
[MessagePackObject(keyAsPropertyName: true)]
public class Person2
{
public string Name { get; set; }
public int Age { get; set; }
}
不過呢,使用 KeyAttribute 序列化的結果會比較小,如果很介意記憶體的影響,建議選用 KeyAttribute 的方式。
沒有特殊情況下,序列化與反序列化也非常簡單,直接呼叫 MessagePackSerializer class 的靜態方法即可,例如:
Person p1 = new Person { Name = "Bill", Age = 36 };
byte[] b1 = MessagePackSerializer.Serialize(p1);
Person p1_1 = MessagePackSerializer.Deserialize<Person>(b1);
比較序列化後的長度
在我的 github 上有個簡單的範例,介紹基本用法外順帶做了個簡單的比較
static void Main(string[] args)
{
/// Person class is serialized with key as index
Person p1 = new Person { Name = "Bill", Age = 36 };
byte[] b1 = MessagePackSerializer.Serialize(p1);
Person p1_1 = MessagePackSerializer.Deserialize<Person>(b1);
Console.WriteLine($"Name : {p1_1.Name}, Age : {p1_1.Age}, serialization length : {b1.Length}");
/// Person2 class is serialized with key as property name
Person2 p2 = new Person2 { Name = "Bill", Age = 36 };
byte[] b2 = MessagePackSerializer.Serialize(p2);
Person2 p2_1 = MessagePackSerializer.Deserialize<Person2>(b2);
Console.WriteLine($"Name : {p2_1.Name}, Age : {p2_1.Age}, serialization length : {b2.Length}");
/// Person class is serialized by System.Text.Json
string json = JsonSerializer.Serialize(p1);
byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
Person p1_2 = JsonSerializer.Deserialize<Person>(jsonBytes);
Console.WriteLine($"Name : {p1_2.Name}, Age : {p1_2.Age}, serialization length : {jsonBytes.Length}");
}
得到的結果是這樣的:
Name : Bill, Age : 36, serialization length : 7
Name : Bill, Age : 36, serialization length : 16
Name : Bill, Age : 36, serialization length : 24
可以看到 JSON 序列化後的陣列長度是最長的,MessagePack 採用屬性名稱作為鍵值的長度次之,而 MessagePack 採用整數作為鍵值的長度則是最短。