Skip to content

Instantly share code, notes, and snippets.

@NickStrupat
Last active December 4, 2024 21:21
Show Gist options
  • Save NickStrupat/0093d6b84ae2d784e6484123c7922fcf to your computer and use it in GitHub Desktop.
Save NickStrupat/0093d6b84ae2d784e6484123c7922fcf to your computer and use it in GitHub Desktop.
JSON serialization of a stream
using System.Buffers.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
var text = "Hello, World! How are ya? Good! That's swell!"u8;
{
using var ms = new MemoryStream(text.ToArray());
var foo = new Foo("text", ms);
using var fs = File.Create("yes.txt", 4096, FileOptions.WriteThrough);
JsonSerializerOptions jso = new() { Converters = { new StreamToBase64WriteOnlyJsonConverter(fs) }};
using var writer = new Utf8JsonWriter(fs);
JsonSerializer.Serialize(writer, foo, jso);
}
var json = File.ReadAllText("yes.txt");
Console.WriteLine(json);
Console.WriteLine(Convert.ToBase64String(text));
record Foo(string Name, Stream Reader);
public sealed class StreamToBase64WriteOnlyJsonConverter(Stream writeStream) : JsonConverter<Stream>
{
public override Stream Read(ref Utf8JsonReader r, Type ttc, JsonSerializerOptions o) => throw new NotImplementedException();
public override void Write(Utf8JsonWriter writer, Stream value, JsonSerializerOptions options)
{
writer.WriteNumberValue(0); // write a dummy value so the writer knows it has written a value
writer.Flush(); // flush the writer to the underlying stream
writeStream.Position -= 1; // move the stream back one byte to overwrite the dummy value
writeStream.Write("\""u8);
Span<byte> buffer = stackalloc byte[4];
var maxNonBase64Bytes = Base64.GetMaxDecodedFromUtf8Length(buffer.Length);
int read;
while ((read = value.Read(buffer[..maxNonBase64Bytes])) != 0)
{
Base64.EncodeToUtf8InPlace(buffer, read, out var bytesWritten);
writeStream.Write(buffer[..bytesWritten]);
}
writeStream.Write("\""u8);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment