MessagePackSerializer类是MessagePack for C# 的入口点。静态方法构成了MessagePack for C# 的主要API。
| API | Description |
|---|---|
Serialize | 将一个对象图序列化为MessagePack二进制块。可以使用异步变体获取Stream。也有非泛型重载可用。 |
Deserialize | 将MessagePack二进制转换为对象图。可用于Stream的异步变体。也有非泛型重载可用。 |
SerializeToJson | 将MessagePack兼容的对象图序列化为JSON,而不是MessagePack。这对调试很有帮助。 |
ConvertToJson | 将MessagePack二进制转换为JSON。这对调试很有帮助 |
ConvertFromJson | 将JSON转换为MessagePack二进制。 |
MessagePack for C#基本上使用IBufferWriter
高级API内部使用内存池来避免不必要的内存分配。如果结果大小小于64K,则只为返回字节分配GC内存。
每个serialize / deserialize方法都可选地接受一个MessagePackSerializerOptions参数,可用于指定要使用的自定义IFormatterResolver或激活LZ4压缩支持。
要反序列化包含多个连续MessagePack数据结构的流,您可以使用MessagePackStreamReader类来高效地识别每个数据结构的ReadOnlySequence
- static async Task<List<T>> DeserializeListFromStreamAsync<T>(Stream stream, CancellationToken cancellationToken)
- {
- var dataStructures = new List
(); - using (var streamReader = new MessagePackStreamReader(stream))
- {
- while (await streamReader.ReadAsync(cancellationToken) is ReadOnlySequence<byte> msgpack)
- {
- dataStructures.Add(MessagePackSerializer.Deserialize
(msgpack, cancellationToken: cancellationToken)); - }
- }
-
- return dataStructures;
- }
IMessagePackFormatter
- public interface IMessagePackFormatter<T>
- {
- void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options);
- T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options);
- }
有许多内置格式器位于MessagePack.Formatters下。你的自定义类型通常会自动得到支持,并使用动态代码生成来生成新IMessagePackFormatter
然而,一些类型(特别是由第三方库或运行时本身提供的类型)无法适当地注解,无合同序列化会产生效率低下甚至错误的结果。为了更好地控制此类自定义类型的序列化,编写您自己的IMessagePackFormatter
- /// <summary>Serializes a <see cref="FileInfo" /> by its full path as a string.</summary>
- public class FileInfoFormatter : IMessagePackFormatter<FileInfo>
- {
- public void Serialize(
- ref MessagePackWriter writer, FileInfo value, MessagePackSerializerOptions options)
- {
- if (value == null)
- {
- writer.WriteNil();
- return;
- }
-
- writer.WriteString(value.FullName);
- }
-
- public FileInfo Deserialize(
- ref MessagePackReader reader, MessagePackSerializerOptions options)
- {
- if (reader.TryReadNil())
- {
- return null;
- }
-
- options.Security.DepthStep(ref reader);
-
- var path = reader.ReadString();
-
- reader.Depth--;
- return new FileInfo(path);
- }
- }
DepthStep 和 Depth--语句提供了一层安全保护,在反序列化不受信任的数据时,可能会导致拒绝服务攻击,发送会导致堆栈溢出异常的消息包数据,并崩溃进程。这两个语句应该包围任何IMessagePackFormatter
注意:一个message pack 格式器必须读写一个数据结构。在上述例子中我们只是读取或写入一个字符串。如果你有多个元素要写入,必须在前面加上map或array头。在反序列化时必须读取整个map/array。例如:
- public class MySpecialObjectFormatter : IMessagePackFormatter<MySpecialObject>
- {
- public void Serialize(
- ref MessagePackWriter writer, MySpecialObject value, MessagePackSerializerOptions options)
- {
- if (value == null)
- {
- writer.WriteNil();
- return;
- }
-
- writer.WriteArrayHeader(2);
- writer.WriteString(value.FullName);
- writer.WriteString(value.Age);
- }
-
- public MySpecialObject Deserialize(
- ref MessagePackReader reader, MessagePackSerializerOptions options)
- {
- if (reader.TryReadNil())
- {
- return null;
- }
-
- options.Security.DepthStep(ref reader);
-
- string fullName = null;
- int age = 0;
-
- // Loop over *all* array elements independently of how many we expect,
- // since if we're serializing an older/newer version of this object it might
- // vary in number of elements that were serialized, but the contract of the formatter
- // is that exactly one data structure must be read, regardless.
- // Alternatively, we could check that the size of the array/map is what we expect
- // and throw if it is not.
- int count = reader.ReadArrayHeader();
- for (int i = 0; i < count; i++)
- {
- switch (i)
- {
- case 0:
- fullName = reader.ReadString();
- break;
- case 1:
- age = reader.ReadInt32();
- break;
- default:
- reader.Skip();
- break;
- }
- }
-
- reader.Depth--;
- return new MySpecialObject(fullName, age);
- }
- }
Unity最低支持版本为2018.3,API 兼容级别同时支持.NET 4.x 和.NET Standard 2.0。
可以从Release 页面安装unitypackage。如果构建目标是.NET Framework 4.x 并在mono上运行,可以直接使用它。但如果构建目标是IL2CPP,则不能使用Dynamic***Resolver,因此需要使用预代码生成。请参阅预代码生成部分。
MessagePack for C# 包含一些NuGet中原先提供的额外System.*.dll库。它们位于Plugins文件夹下。如果其他包使用这些库(例如使用System.Runtime.CompilerServices.Unsafe.dll的Unity Collections包),为了避免冲突,请删除Plugins下的DLL。
目前CompositeResolver.Create在IL2Cpp上不起作用,因此建议使用StaticCompositeResolver.Instance.Register。
在Unity中,MessagePackSerializer可以使用内置扩展UnityResolver将Vector2、Vector3、Vector4、Quaternion、Color、Bounds、Rect、AnimationCurve、Keyframe、Matrix4x4、Gradient、Color32、RectOffset、LayerMask、Vector2Int、Vector3Int、RangeInt、RectInt、BoundsInt及其可空、数组和列表类型序列化。它默认包含在StandardResolver中。
MessagePack for C# 还有一个额外的不安全扩展。UnsafeBlitResolver 是一个特殊解析器,用于结构数组的极高但不安全的序列化/反序列化