(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 序列化流的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 System.Text.Json 忽略错误值

使用 System.Text.Json 修改 JSON 文件

如何在反序列化之前使用 System.Text.Json 验证 JSON

使用 System.Text.Json 转换不一致的 json 值 [重复]

使用 .NET core 3.0/System.text.Json 解析 JSON 文件

使用 System.Text.Json 序列化 BigInteger