序列化 反序列化 MessagePack for C#

MessagePack for C#git

快速序列化組件MessagePack介紹

 

簡介

MessagePack for C#(MessagePack-CSharp)是用於C#的極速MessagePack序列化程序,比MsgPack-Cli快10倍,與其餘全部C#序列化程序相比,具備最好的性能。 MessagePack for C#具備內置的LZ4壓縮功能,能夠實現超快速序列化和二進制佔用空間小。 性能永遠是重要的! 可用於遊戲,分佈式計算,微服務,數據存儲到Redis等。支持.NET, .NET Core, Unity, Xamarin。github

從上圖咱們看出MessagePack for C#在性能測試中是最好的,這裏解釋一下第三個MsgPack-Cli是MessagePack官方實現的。第一和第二都是MessagePack for C#,第一項相比第二項具備稍快一點的序列化和反序列化速度,可是第二項採用了L4壓縮功能,顯著的減小了二進制的大小。在實際使用中推薦使用L4壓縮功能。算法

使用

該組件已經發布在Nuget,使用命令加入項目。sql

Install-Package MessagePackjson

分析器api

Install-Package MessagePackAnalyzer數組

擴展緩存

Install-Package MessagePack.ImmutableCollection
Install-Package MessagePack.ReactiveProperty
Install-Package MessagePack.UnityShims
Install-Package MessagePack.AspNetCoreMvcFormatter

Unity在此處下載 https://github.com/neuecc/MessagePack-CSharp/releasesmarkdown

快速開始

定義一個類添加[MessagePackObject]特性,公共成員(屬性或者字段)添加[Key]特性,調用MessagePackSerializer.Serialize<T>/Deserialize<T>進行序列化和反序列化,ToJson能夠幫咱們轉儲二進制爲json格式。

// 標記 MessagePackObjectAttribute [MessagePackObject] public class MyClass { // Key 是序列化索引,對於版本控制很是重要。 [Key(0)] public int Age { get; set; } [Key(1)] public string FirstName { get; set; } [Key(2)] public string LastName { get; set; } // 公共成員中不序列化目標,標記IgnoreMemberAttribute [IgnoreMember] public string FullName { get { return FirstName + LastName; } } }
class Program { static void Main(string[] args) { var mc = new MyClass { Age = 99, FirstName = "hoge", LastName = "huga", }; // 序列化 var bytes = MessagePackSerializer.Serialize(mc); //反序列化 var mc2 = MessagePackSerializer.Deserialize<MyClass>(bytes); // 你能夠將msgpack二進制轉儲爲可讀的json。 // 在默認狀況下,MeesagePack for C#減小了屬性名稱信息。 // [99,"hoge","huga"] var json = MessagePackSerializer.ToJson(bytes); Console.WriteLine(json); Console.ReadKey(); } }

序列化索引將會影響該信息在序列化數據中的位置

默認狀況下特性是必須的,可是咱們有方法進行改變,讓它變爲不是必須的,詳情請看後面。

分析器

MessagePackAnalyzer 能夠幫助咱們定義對象. 若是不符合規則,那麼特性, 程序集等能夠被檢測到,若是咱們編譯就會出現編譯錯誤。

若是要容許特定類型(例如,註冊自定義類型時),請將MessagePackAnalyzer.json放在項目根目錄下,並將生成操做設置爲AdditionalFiles(其餘文件)。

這是MessagePackAnalyzer.json內容的一個示例。

[ "MyNamespace.FooClass", "MyNameSpace.BarStruct" ]

內置的支持類型

這些類型能夠默認序列化。

基元(int、string等等), Enum, Nullable<>, TimeSpan, DateTime, DateTimeOffset, Nil, Guid, Uri, Version, StringBuilder, BitArray, ArraySegment<>, BigInteger, Complext, Task, Array[], Array[,], Array[,,], Array[,,,], KeyValuePair<,>, Tuple<,...>, ValueTuple<,...>, List<>, LinkedList<>, Queue<>, Stack<>, HashSet<>, ReadOnlyCollection<>, IList<>, ICollection<>, IEnumerable<>, Dictionary<,>, IDictionary<,>, SortedDictionary<,>, SortedList<,>, ILookup<,>, IGrouping<,>, ObservableCollection<>, ReadOnlyOnservableCollection<>, IReadOnlyList<>, IReadOnlyCollection<>, ISet<>, ConcurrentBag<>, ConcurrentQueue<>, ConcurrentStack<>, ReadOnlyDictionary<,>, IReadOnlyDictionary<,>, ConcurrentDictionary<,>, Lazy<>, Task<>, 自定義繼承ICollection <>或IDictionary <,>具備無參構造方法, IList,IDictionary和自定義繼承ICollection或IDictionary具備無參構造函數(包括ArrayList和Hashtable)。

您能夠添加自定義類型的支持和一些官方/第三方擴展包。 對於ImmutableCollections(ImmutableList <>等),對於ReactiveProperty和Unity(Vector3, Quaternion等等),對於F#(Record,FsList,Discriminated Unions等)。

MessagePack.Nil是MessagePack for C#的內置null/void/unit表示類型。

對象序列化

MessagePack for C#能夠序列化public Class或Struct,序列化目標必須標記[MessagePackObject]和[Key], Key類型能夠選擇int或字符串。若是Key類型是int,則使用序列化格式爲數組,若是Key類型是字符串,則使用序列化格式爲鍵值對,若是您定義了[MessagePackObject(keyAsPropertyName:true)],則不須要Key特性。

[MessagePackObject] public class Sample1 { [Key(0)] public int Foo { get; set; } [Key(1)] public int Bar { get; set; } } [MessagePackObject] public class Sample2 { [Key("foo")] public int Foo { get; set; } [Key("bar")] public int Bar { get; set; } } [MessagePackObject(keyAsPropertyName: true)] public class Sample3 { // 不須要key特性 public int Foo { get; set; } // 不須要序列化的成員使用IgnoreMember特性 [IgnoreMember] public int Bar { get; set; } } // 結果 [10,20] Console.WriteLine(MessagePackSerializer.ToJson(new Sample1 { Foo = 10, Bar = 20 })); // 結果 {"foo":10,"bar":20} Console.WriteLine(MessagePackSerializer.ToJson(new Sample2 { Foo = 10, Bar = 20 })); // 結果 {"Foo":10} Console.WriteLine(MessagePackSerializer.ToJson(new Sample3 { Foo = 10, Bar = 20 }));

全部模式序列化目標都是公共實例成員(字段或屬性)。 若是要避免序列化目標,能夠將[IgnoreMember]添加到目標成員。

目標類必須是 public, 不容許 private, internal 類.

應該使用哪一種Key類型,int或string? 做者建議使用int key,由於比string key更快,更緊湊。 可是string key有關鍵的名字信息,對調試頗有用。

MessagePackSerializer序列化目標時,必須在目標使用特性才能保證穩健性,若是類進行了擴充,你必須意識到版本控制。若是Key不存在,MessagePackSerializer將會使用默認值。若是使用的是int key,那麼必須從0開始,若是沒必要要的屬性出現,請填寫空缺的數字。重用是很差的。 此外,若是Int Key的跳轉數字差距太大,則會影響二進制大小。

[MessagePackObject] public class IntKeySample { [Key(3)] public int A { get; set; } [Key(10)] public int B { get; set; } } // int key不從0開始而且數字進行了跳躍,將會出現下面的結果 //[null,null,null,0,null,null,null,null,null,null,0] Console.WriteLine(MessagePackSerializer.ToJson(new IntKeySample()));

若是你想像JSON.NET那樣使用!不想加特性! 若是你這樣想,你可使用無約定的解析器。

public class ContractlessSample { public int MyProperty1 { get; set; } public int MyProperty2 { get; set; } } var data = new ContractlessSample { MyProperty1 = 99, MyProperty2 = 9999 }; var bin = MessagePackSerializer.Serialize(data, MessagePack.Resolvers.ContractlessStandardResolver.Instance); // {"MyProperty1":99,"MyProperty2":9999} Console.WriteLine(MessagePackSerializer.ToJson(bin)); // 全局設置無約束解析器爲默認解析器 MessagePackSerializer.SetDefaultResolver(MessagePack.Resolvers.ContractlessStandardResolver.Instance); // 序列化 var bin2 = MessagePackSerializer.Serialize(data); 

我想序列化私人成員! 默認狀況下,不能序列化/反序列化私有成員。 可是你可使用allow-private解析器來序列化私人成員。

[MessagePackObject] public class PrivateSample { [Key(0)] int x; public void SetX(int v) { x = v; } public int GetX() { return x; } } var data = new PrivateSample(); data.SetX(9999); // 你能夠選擇 StandardResolverAllowPrivate 或者 ContractlessStandardResolverAllowPrivate 解析器 var bin = MessagePackSerializer.Serialize(data, MessagePack.Resolvers.DynamicObjectResolverAllowPrivate.Instance);

我不須要類型,我想像BinaryFormatter那樣使用! 你可使用無類型的解析器和幫助器。 請參閱Typeless部分。

解析器是MessagePack For C#的關鍵定製點。 詳情請見擴展部分。

DataContract兼容性

您可使用[DataContract]而不是[MessagePackObject]。 若是type標記爲DataContract,則可使用[DataMember]代替[Key],[IgnoreDataMember]代替[IgnoreMember]。

[DataMember(Order = int)] 和 [Key(int)]相同, [DataMember(Name = string)]和 [Key(string)]相同. 若是使用 [DataMember], 則相似於 [Key(nameof(propertyname)].

使用DataContract使其成爲一個共享的類庫,您沒必要引用MessagePack for C#。 可是,它不包含在分析器或由mpc.exe生成的代碼中。此外,像UnionAttribute,MessagePackFormatterAttribute,SerializationConstructorAttribute等功能不能使用。 出於這個緣由,我建議您基本上使用MessagePack for C#特性。

序列化不可變對象(序列化構造器)

MessagePack for C#支持反序列化不可變對象。 例如,這個struct能夠天然地序列化/反序列化。

[MessagePackObject] public struct Point { [Key(0)] public readonly int X; [Key(1)] public readonly int Y; public Point(int x, int y) { this.X = x; this.Y = y; } } var data = new Point(99, 9999); var bin = MessagePackSerializer.Serialize(data); // Okay to deserialize immutable obejct var point = MessagePackSerializer.Deserialize<Point>(bin);

MessagePackSerializer choose constructor with the least matched argument, match index if key in integer or match name(ignore case) if key is string. If encounts MessagePackDynamicObjectResolverException: can't find matched constructor parameter you should check about this.

MessagePackSerializer選擇具備最少參數的構造方法,若是key是整型將匹配索引或者若是key是字符串將匹配名稱(忽略大小寫)。 若是遇到 MessagePackDynamicObjectResolverException: can't find matched constructor parameter你應該檢查一會下。

若是不能自動匹配,能夠經過[SerializationConstructorAttribute]手動指定使用構造函數。

[MessagePackObject] public struct Point { [Key(0)] public readonly int X; [Key(1)] public readonly int Y; // 若是沒有標記特性,將會使用這方法(最少參數) public Point(int x) { X = x; } [SerializationConstructor] public Point(int x, int y) { this.X = x; this.Y = y; } }

序列化回調

若是對象實現了IMessagePackSerializationCallbackReceiver,則接受OnBeforeSerializeOnAfterDeserialize序列化處理。

[MessagePackObject] public class SampleCallback : IMessagePackSerializationCallbackReceiver { [Key(0)] public int Key { get; set; } public void OnBeforeSerialize() { Console.WriteLine("OnBefore"); } public void OnAfterDeserialize() { Console.WriteLine("OnAfter"); } }

Union

MessagePack for C#支持序列化接口。這就像XmlInclude或ProtoInclude。在MessagePack for C#裏叫Union。UnionAttribute只能附加到接口或抽象類。 它須要區分的整型key和子類型

// mark inheritance types [MessagePack.Union(0, typeof(FooClass))] [MessagePack.Union(1, typeof(BarClass))] public interface IUnionSample { } [MessagePackObject] public class FooClass : IUnionSample { [Key(0)] public int XYZ { get; set; } } [MessagePackObject] public class BarClass : IUnionSample { [Key(0)] public string OPQ { get; set; } } // --- IUnionSample data = new FooClass() { XYZ = 999 }; // serialize interface. var bin = MessagePackSerializer.Serialize(data); // deserialize interface. var reData = MessagePackSerializer.Deserialize<IUnionSample>(bin); // use type-switch of C# 7.0 switch (reData) { case FooClass x: Console.WriteLine(x.XYZ); break; case BarClass x: Console.WriteLine(x.OPQ); break; default: break; }

C#7.0 type-switch是Union的最佳選擇。 Union被序列化爲兩個長度的數組。

IUnionSample data = new BarClass { OPQ = "FooBar" }; var bin = MessagePackSerializer.Serialize(data); // Union is serialized to two-length array, [key, object] // [1,["FooBar"]] Console.WriteLine(MessagePackSerializer.ToJson(bin));

在抽象類中使用Union,你能夠像接口那樣使用。

[Union(0, typeof(SubUnionType1))] [Union(1, typeof(SubUnionType2))] [MessagePackObject] public abstract class ParentUnionType { [Key(0)] public int MyProperty { get; set; } } [MessagePackObject] public class SubUnionType1 : ParentUnionType { [Key(1)] public int MyProperty1 { get; set; } } [MessagePackObject] public class SubUnionType2 : ParentUnionType { [Key(1)] public int MyProperty2 { get; set; } }

繼承類型的序列化,在數組(或鍵值對)中是扁平化的,對於整型鍵是可有可無的,它不能複製父類和全部的子類。

Dynamic(Untyped)反序列化

若是使用MessagePackSerializer.Deserialize<object> 或者MessagePackSerializer.Deserialize<dynamic>,messagepack將轉換爲 primitive values,msgpack-primitive將轉換爲bool, char, sbyte, byte, short, int, long, ushort, uint, ulong, float, double, DateTime, string, byte[], object[], IDictionary<object, object>.

// sample binary. var model = new DynamicModel { Name = "foobar", Items = new[] { 1, 10, 100, 1000 } }; var bin = MessagePackSerializer.Serialize(model, ContractlessStandardResolver.Instance); // dynamic, untyped var dynamicModel = MessagePackSerializer.Deserialize<dynamic>(bin, ContractlessStandardResolver.Instance); Console.WriteLine(dynamicModel["Name"]); // foobar Console.WriteLine(dynamicModel["Items"][2]); // 100

因此你可使用索引訪問鍵值對或者數組。

Object 類型序列化

StandardResolverContractlessStandardResolver能夠經過DynamicObjectTypeFallbackResolver將Object類型序列化爲具體類型。

var objects = new object[] { 1, "aaa", new ObjectFieldType { Anything = 9999 } }; var bin = MessagePackSerializer.Serialize(objects); // [1,"aaa",[9999]] Console.WriteLine(MessagePackSerializer.ToJson(bin)); // Support Anonymous Type Serialize var anonType = new { Foo = 100, Bar = "foobar" }; var bin2 = MessagePackSerializer.Serialize(anonType, MessagePack.Resolvers.ContractlessStandardResolver.Instance); // {"Foo":100,"Bar":"foobar"} Console.WriteLine(MessagePackSerializer.ToJson(bin2));

Unity支持是有限的。

反序列化時,與Dynamic(Untyped)反序列化相同。

Typeless

Typeless API就像BinaryFormatter, 將類型信息嵌入到二進制中,因此不須要類型去反序列化.

object mc = new Sandbox.MyClass() { Age = 10, FirstName = "hoge", LastName = "huga" }; // serialize to typeless var bin = MessagePackSerializer.Typeless.Serialize(mc); // binary data is embeded type-assembly information. // ["Sandbox.MyClass, Sandbox",10,"hoge","huga"] Console.WriteLine(MessagePackSerializer.ToJson(bin)); // can deserialize to MyClass with typeless var objModel = MessagePackSerializer.Typeless.Deserialize(bin) as MyClass;

類型信息由mspgack ext格式序列化,typecode爲100。

MessagePackSerializer.TypelessSerialize / Deserialize <object>(TypelessContractlessStandardResolver.Instance)的快捷方式。 若是要配置默認的Typeless解析器,能夠經過MessagePackSerializer.Typeless.RegisterDefaultResolver進行設置。

性能

與其餘序列化器在Windows 10 Pro x64 Intel Core i7-6700K 4.00GHz, 32GB RAM上進行Benchmarks比較,Benchmark代碼在這-版本信息,ZeroFormatter和FlatBuffers具備很是快速的反序列化器,所以忽略反序列化的性能。

MessagePack for C#使用許多技術來提升性能。

  • 序列化只使用ref byte []和int offset,不使用(Memory)Stream(調用Stream api會有開銷)
  • 高級API使用內部內存池,分配工做內存不要低於64k
  • 不建立中間實用程序實例(XxxWriter / Reader,XxxContext等)
  • 全部代碼避免裝箱,全部平臺(包括Unity / IL2CPP)
  • 對靜態泛型字段生成的格式化程序進行緩存,查找時從緩存查找(不使用字典緩存,由於字典查找須要必定開銷)
  • 從新調整的動態代碼生成
  • 當代碼生成知道目標是primitive時直接調用PrimitiveAPI
  • 當代碼生成知道目標(整數/字符串)範圍時,減小可變長度格式的分支
  • 不在迭代集合上使用IEnumerable<T> 抽象
  • 使用預先生成的查找表來減小檢查消息包類型所耗時間
  • 對非泛型方法使用優化類型key字典
  • 避免查找映射(字符串鍵)鍵的字符串鍵解碼,並使用自動化名稱查找與il內聯代碼生成
  • 對於字符串鍵編碼,預先生成的成員名字節並在IL中使用固定大小的二進制副本

在建立這個庫以前,做則實現了一個具備ZeroFormatter#Performance的快速序列化器。 這是一個進一步演變的實現。 MessagePack for C#始終是快速的,爲全部類型(原始,小結構,大對象,任何集合)進行了優化。

反序列化中每一個方法的性能

性能取決於選項。 這是一個BenchmarkDotNet的微型benchamark。 目標對象有9個成員(MyProperty1〜MyProperty9),值爲零。

Method Mean Error Scaled Gen 0 Allocated
IntKey 72.67 ns NA 1.00 0.0132 56 B
StringKey 217.95 ns NA 3.00 0.0131 56 B
Typeless_IntKey 176.71 ns NA 2.43 0.0131 56 B
Typeless_StringKey 378.64 ns NA 5.21 0.0129 56 B
MsgPackCliMap 1,355.26 ns NA 18.65 0.1431 608 B
MsgPackCliArray 455.28 ns NA 6.26 0.0415 176 B
ProtobufNet 265.85 ns NA 3.66 0.0319 136 B
Hyperion 366.47 ns NA 5.04 0.0949 400 B
JsonNetString 2,783.39 ns NA 38.30 0.6790 2864 B
JsonNetStreamReader 3,297.90 ns NA 45.38 1.4267 6000 B
JilString 553.65 ns NA 7.62 0.0362 152 B
JilStreamReader 1,408.46 ns NA 19.38 0.8450 3552 B

IntKey,StringKey,Typeless_IntKey,Typeless_StringKey都是MessagePack for C#的方法
,在反序列化過程當中實現零內存分配。JsonNetString /JilString從字符串反序列化。JsonStStreamReader / JilStreamReader是從StreamReader的UTF8 byte []中反序列化的。反序列化一般從Stream讀取。 所以,它將從字節數組(或流)而不是字符串中讀取。

MessagePack for C#IntKey是最快的。 StringKey比IntKey慢,由於StringKey須要從字符串進行匹配。 若是是IntKey,讀取數組長度,根據數組長度進行for循環二進制解碼。 若是StringKey,讀取map 長度,根據map長度循環,首先須要對密鑰解碼,而後按照key查找,最後二進制解碼,則須要額外兩個步驟(解碼密鑰和按鍵查找)。

字符串鍵一般是有用的,無約束的,簡單的JSON替換,與其餘語言的互操做性,以及更多的某些版本。 MessagePack for C#也爲String Key進行了優化。 首先,它不會將UTF8字節數組解碼爲與成員名稱匹配的字符串,它會按原樣查找字節數組(避免解碼成本和額外分配)。

它會嘗試匹配每一個長整型(long)(每8個字符,若是長度不夠,填充0)使用automata和在生成時內聯IL代碼。

這也避免了計算字節數組的哈希碼,而且能夠在長單元上進行屢次比較。

這是ILSpy生成的反序列化器代碼的示例的反編譯。

https://github.com/neuecc/MessagePack-CSharp#performance

若是節點數量很大,則使用嵌入式二進制搜索進行搜索。

另外請注意,這是序列化的基準測試結果。

Method Mean Error Scaled Gen 0 Allocated
IntKey 84.11 ns NA 1.00 0.0094 40 B
StringKey 126.75 ns NA 1.51 0.0341 144 B
Typeless_IntKey 183.31 ns NA 2.18 0.0265 112 B
Typeless_StringKey 193.95 ns NA 2.31 0.0513 216 B
MsgPackCliMap 967.68 ns NA 11.51 0.1297 552 B
MsgPackCliArray 284.20 ns NA 3.38 0.1006 424 B
ProtobufNet 176.43 ns NA 2.10 0.0665 280 B
Hyperion 280.14 ns NA 3.33 0.1674 704 B
ZeroFormatter 149.95 ns NA 1.78 0.1009 424 B
JsonNetString 1,432.55 ns NA 17.03 0.4616 1944 B
JsonNetStreamWriter 1,775.72 ns NA 21.11 1.5526 6522 B
JilString 547.51 ns NA 6.51 0.3481 1464 B
JilStreamWriter 778.78 ns NA 9.26 1.4448 6066 B

固然,IntKey是最快的,但StringKey也不錯。

LZ4壓縮

MessagePack是一個快速和緊湊的格式,但它不是壓縮格式。 LZ4是很是快速的壓縮算法,使用MessagePack for C#能夠實現極快的性能和很是緊湊的二進制大小!

MessagePack for C#具備內置的LZ4支持。 您可使用LZ4MessagePackSerializer而不是MessagePackSerializer。 內建支持是特殊的,做者已經建立了序列化壓縮管道,並專門調整了管道,因此共享工做內存,不分配,不要調整,直到完成。

序列化二進制不是簡單地壓縮lz4二進制。 序列化二進制是有效的MessagePack二進制使用ext格式和自定義typecode(99)。

var array= Enumerable.Range(1, 100).Select(x => new MyClass { Age = 5, FirstName = "foo", LastName = "bar" }).ToArray(); // call LZ4MessagePackSerializer instead of MessagePackSerializer, api is completely same var lz4Bytes = LZ4MessagePackSerializer.Serialize(array); var mc2 = LZ4MessagePackSerializer.Deserialize<MyClass[]>(lz4Bytes); // you can dump lz4 message pack // [[5,"hoge","huga"],[5,"hoge","huga"],....] var json = LZ4MessagePackSerializer.ToJson(lz4Bytes); Console.WriteLine(json); // lz4Bytes is valid MessagePack, it is using ext-format( [TypeCode:99, SourceLength|CompressedBinary] ) // [99,"0gAAA+vf3ABkkwWjZm9vo2JhcgoA////yVBvo2Jhcg=="] var rawJson = MessagePackSerializer.ToJson(lz4Bytes); Console.WriteLine(rawJson);

與protobuf,JSON,ZeroFormatter比較

protbuf-net是.NET上最經常使用的二進制格式化庫。 我(做者)喜歡protobuf-net,並尊重那偉大的工做。 可是若是使用protobuf-net做爲通用序列化格式,則可能會引發煩人的問題。

[ProtoContract] public class Parent { [ProtoMember(1)] public int Primitive { get; set; } [ProtoMember(2)] public Child Prop { get; set; } [ProtoMember(3)] public int[] Array { get; set; } } [ProtoContract] public class Child { [ProtoMember(1)] public int Number { get; set; } } using (var ms = new MemoryStream()) { // serialize null. ProtoBuf.Serializer.Serialize<Parent>(ms, null); ms.Position = 0; var result = ProtoBuf.Serializer.Deserialize<Parent>(ms); Console.WriteLine(result != null); // True, not null. but all property are zero formatted. Console.WriteLine(result.Primitive); // 0 Console.WriteLine(result.Prop); // null Console.WriteLine(result.Array); // null } using (var ms = new MemoryStream()) { // serialize empty array. ProtoBuf.Serializer.Serialize<Parent>(ms, new Parent { Array = new int[0] }); ms.Position = 0; var result = ProtoBuf.Serializer.Deserialize<Parent>(ms); Console.WriteLine(result.Array == null); // True, null! }

protobuf(-net)不能正確處理null和空集合。 由於protobuf沒有null表示(這是protobuf-net做者的答案)。

MessagePack規範能夠徹底序列化C#類型。 這就是推薦MessagePack而不是protobuf的緣由。

Protocol Buffers具備良好的IDL和gRPC,這比MessagePack好得多。 若是你想使用IDL,我(做者)推薦Google.Protobuf。

JSON是很好的通用格式。 這是完美的,簡單的,足夠規範的。 Utf8Json建立了我採用與MessagePack for C#相同的體系結構,並避免編碼/修飾成本,因此像二進制同樣工做。 若是你想了解二進制與文本,請參閱Utf8Json /應使用哪一個序列化器部分。

ZeroFormatter與FlatBuffers相似,但專門用於C#。 這是特別的。 反序列化速度很是快,可是二進制大小卻很大。 而ZeroFormatter的緩存算法須要額外的內存。

ZeroFormatter也是特別的。 當與ZeroFormatter對比的狀況下,它顯示格式化的力量。 可是對於許多常見的用途,MessagePack for C#會更好。

擴展

MessagePack for C#具備擴展點,您能夠添加外部類型的序列化支持。 下列是官方擴展支持。

Install-Package MessagePack.ImmutableCollection Install-Package MessagePack.ReactiveProperty Install-Package MessagePack.UnityShims Install-Package MessagePack.AspNetCoreMvcFormatter

MessagePack.ImmutableCollection添加對 System.Collections.Immutable的支持. 添加了對ImmutableArray<>, ImmutableList<>, ImmutableDictionary<,>, ImmutableHashSet<>, ImmutableSortedDictionary<,>, ImmutableSortedSet<>, ImmutableQueue<>, ImmutableStack<>, IImmutableList<>, IImmutableDictionary<,>, IImmutableQueue<>, IImmutableSet<>, IImmutableStack<>的序列化支持.

MessagePack.ReactiveProperty包添加對ReactiveProperty庫的支持。它增長了ReactiveProperty <>,IReactiveProperty <>,IReadOnlyReactiveProperty <>,ReactiveCollection <>,unit序列化支持。 這對保存視圖模型狀態頗有用。

MessagePack.AspNetCoreMvcFormatter是ASP.NET Core MVC序列化的附加組件,可提高性能。 這是配置示例。

public void ConfigureServices(IServiceCollection services) { services.AddMvc().AddMvcOptions(option => { option.OutputFormatters.Clear(); option.OutputFormatters.Add(new MessagePackOutputFormatter(ContractlessStandardResolver.Instance)); option.InputFormatters.Clear(); option.InputFormatters.Add(new MessagePackInputFormatter(ContractlessStandardResolver.Instance)); }); }

更多信息請訪問github: https://github.com/neuecc/MessagePack-CSharp

相關文章
相關標籤/搜索