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> DeserializeListFromStreamAsync(Stream stream, CancellationToken cancellationToken)
{
var dataStructures = new List();
using (var streamReader = new MessagePackStreamReader(stream))
{
while (await streamReader.ReadAsync(cancellationToken) is ReadOnlySequence msgpack)
{
dataStructures.Add(MessagePackSerializer.Deserialize(msgpack, cancellationToken: cancellationToken));
}
}
return dataStructures;
}
IMessagePackFormatter
public interface IMessagePackFormatter
{
void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options);
T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options);
}
有许多内置格式器位于MessagePack.Formatters下。你的自定义类型通常会自动得到支持,并使用动态代码生成来生成新IMessagePackFormatter
然而,一些类型(特别是由第三方库或运行时本身提供的类型)无法适当地注解,无合同序列化会产生效率低下甚至错误的结果。为了更好地控制此类自定义类型的序列化,编写您自己的IMessagePackFormatter
/// Serializes a by its full path as a string.
public class FileInfoFormatter : IMessagePackFormatter
{
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
{
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 是一个特殊解析器,用于结构数组的极高但不安全的序列化/反序列化