(de) 使用 System.Text.Json 序列化流

Posted

技术标签:

【中文标题】(de) 使用 System.Text.Json 序列化流【英文标题】:(de)Serializing stream using System.Text.Json 【发布时间】:2021-09-30 07:36:13 【问题描述】:

我正在尝试使用 System.Text.Json 的 JsonSerializer 将对象序列化为 MemoryStream。我无法在文档中找到它的实现/方法。有人可以分享使用 System.Text.Json 进行序列化和反序列化的示例实现吗?

【问题讨论】:

I am unable to find the implementation/method of that in the documentation 你尝试了什么?您检查了哪些文档?你到底想做什么? MemoryStream 只是 byte[] 数组上的 Stream 包装器。 JsonSerializer.SerializeToUtf8Byte 返回一个 byte[] 数组。如果您想将其包装在 MemoryStream 中,您可以使用 MemoryStream(byte[]) 构造函数。 JsonSerializer.Serialize 可以写入 Utf8JsonWriter,而 Utf8JsonWriter 又可以以 Stream 为目标 什么是真正的问题?您使用了 ASP.NET 标记,而 ASP.NET Core 已经使用 System.Text.Json 来序列化响应。不需要直接使用序列化器。 【参考方案1】:

尚不清楚问题出在哪里,或者缺少哪些文档和示例,因为docs.microsoft.com 中有多个部分以及数百篇博客文章和文章。在文档中,JSON serialization and deserialization 是一个很好的起点,How to serialize and deserialize (marshal and unmarshal) JSON in .NET 包含 Serialize to UTF8 部分。

无论如何,MemoryStream 只是 byte[] 数组上的 Stream 包装器,因此序列化到 MemoryStream 与直接序列化到 byte[] 数组相同。这可以通过JsonSerializer.SerializeToUtf8Bytes 来完成:

byte[] jsonUtf8Bytes =JsonSerializer.SerializeToUtf8Bytes(weatherForecast);

最后,在 .NET 中,任何需要序列化的东西都通过 Reader 和 Writer 对象工作,例如 TextReader、StreamReader、TextReader 和 -Writers。在 JSON.NET 的情况下,这是通过 Utf8JsonWriter 对象完成的。 JsonSerializer.Serialize 有一个写入 Utf8JsonWriter 的重载:

using var stream=File.OpenWrite(somePath);
using var writer=new Utf8JsonWriter(stream);
JsonSerializer.Serialize(writer,myObject);

这是使用System.Text.Json 方式。使用缓冲区意味着分配它们并清理它们,这是昂贵的,尤其是在 Web 应用程序中。出于这个原因,ASP.NET Core 使用IO pipelines 而不是流来接收和发送数据到套接字,使用从缓冲池中租用的可重用缓冲区并在 ASP.NET Core 管道中的每个步骤中传递。传递byte[] 缓冲区会复制其内容,因此.NET Core 引入了Span<>Memory<> 类型,它们表示现有(可能是池化的)缓冲区上的视图。这样,ASP.NET Core 会传递缓冲区的这些“视图”,而不是缓冲区本身。

System.Text.Json 旨在使用管道和可重用内存而不是流,从而允许 ASP.NET Core 在高流量网站中使用最少的内存和尽可能少的分配。 ASP.NET Core 使用Utf8JsonWriter(IBufferWriter) 构造函数通过PipeWriter 写入输出管道。

我们可以使用相同的重载写入带有ArrayBufferWriter 的可重用缓冲区。这相当于使用 MemoryStream BUT 输出是通过 ReadOnlySpan<byte>Memory<byte> 访问的,因此不必复制它:

using var buffer=new ArrayBufferWriter<byte>(65536);
using var writer=new Utf8JsonWriter(buffer);
JsonSerializer.Serialize(writer,myObject);

ReadOnlySpan<byte> data=buffer.WrittenSpan;

【讨论】:

【参考方案2】:

更好的选择是使用 newtonsoft.json。

例子很多

【讨论】:

但.Net 建议使用 System.Text.Json 而不是 newtonsoft.json The better option 依据什么标准?尤其是当 JSON.NET 的作者说人们应该使用 System.Text.Json,因为它更快System.Text.Json 也有很多例子,在 docs.microsoft.com 中有自己的部分,过去几年有数百篇文章和博客文章

以上是关于(de) 使用 System.Text.Json 序列化流的主要内容,如果未能解决你的问题,请参考以下文章