(de)Serializing stream using System.Text.Json
Asked Answered
M

1

5

I am trying to serialize an object into a MemoryStream using System.Text.Json's JsonSerializer. I am unable to find the implementation/method of that in the documentation. Can someone share the sample implementation for serialization and deserialization using System.Text.Json?

Morphophoneme answered 23/7, 2021 at 6:4 Comment(0)
M
15

UPDATE

.NET 6 added JsonSerializer.Serialize overloads that write to a stream. It's now possible to write just :

JsonSerializer.Serialize(stream,myObject);

This produces unindented JSON using UTF8 without BOM


Original Answer

It's unclear what the problem is, or what documentation and examples are missing, as there's are multiple sections in learn.microsoft.com and hundreds of blog posts and articles. In the docs JSON serialization and deserialization is a good place to start and How to serialize and deserialize (marshal and unmarshal) JSON in .NET includes the section Serialize to UTF8.

A MemoryStream is just a Stream wrapper over a byte[] array anyway, so serializing to a MemoryStream is the same as serializing to a byte[] array directly. This can be done with JsonSerializer.SerializeToUtf8Bytes:

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

And finally, in .NET anything that needs to serialize to something, works through Reader and Writer objects, like TextReader, StreamReader, TextReader and -Writers. In JSON.NET's case, this is done through the Utf8JsonWriter object. JsonSerializer.Serialize has an overload that writes to a Utf8JsonWriter :

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

That's the slow way of using System.Text.Json though. Using buffers means allocating them and cleaning them up, which is costly, especially in web applications. For this reason, ASP.NET Core uses IO pipelines instead of streams to receive and send data to sockets, using reusable buffers leased from buffer pools and passed along each step in the ASP.NET Core pipeline. Passing byte[] buffers around copies their contents, so .NET Core introduced the Span<> and Memory<> types, which represent a view over an existing (possibly pooled) buffer. This way, ASP.NET Core passes those "views" of the buffers around, not the buffers themselves.

System.Text.Json was built to use pipelines and reusable memory instead of streams, allowing ASP.NET Core to use minimal memory and as few allocations as possible in high traffic web sites. ASP.NET Core uses the Utf8JsonWriter(IBufferWriter) constructor to write to the output pipeline through a PipeWriter.

We can use the same overload to write to a reusable buffer with an ArrayBufferWriter. That's the equivalent of using a MemoryStream BUT the output is accessed through either a ReadOnlySpan<byte> or Memory<byte> so it doesn't have to be copied around :

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

ReadOnlySpan<byte> data=buffer.WrittenSpan;
Muttonhead answered 26/7, 2021 at 7:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.