(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.jsonThe better option
依据什么标准?尤其是当 JSON.NET 的作者说人们应该使用 System.Text.Json,因为它更快? System.Text.Json
也有很多例子,在 docs.microsoft.com
中有自己的部分,过去几年有数百篇文章和博客文章以上是关于(de) 使用 System.Text.Json 序列化流的主要内容,如果未能解决你的问题,请参考以下文章
使用 System.Text.Json 修改 JSON 文件
如何在反序列化之前使用 System.Text.Json 验证 JSON
使用 System.Text.Json 转换不一致的 json 值 [重复]