using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Collections.ObjectModel;
using System.IO.Compression;
using System.Threading.Tasks;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using System.Text.Json.Nodes;
public static class JsonExtensions
public static readonly RecyclableMemoryStreamManager MemoryStreamManager = new RecyclableMemoryStreamManager();
const int BufferSize = 16384;
public static async Task<byte []> CopyAndAddToBCompressedyteArrayAsync<TItem>(byte [] input, IEnumerable<TItem> newItems, JsonSerializerOptions? options = default)
using var inputStream = new MemoryStream(input);
using var outputStream = MemoryStreamManager.GetStream();
await CopyAndAddToCompressedStreamAsync(inputStream, outputStream, newItems, options);
return outputStream.ToArray();
public static async Task CopyAndAddToCompressedFileAsync<TItem>(string inputPath, string outputPath, IEnumerable<TItem> newItems, JsonSerializerOptions? options = default)
using var input = File.OpenRead(inputPath);
using var output = File.OpenWrite(outputPath);
await CopyAndAddToCompressedStreamAsync(input, output, newItems, options);
public static async Task CopyAndAddToCompressedStreamAsync<TItem>(Stream input, Stream output, IEnumerable<TItem> newItems, JsonSerializerOptions? options = default)
options ??= JsonSerializerOptions.Default;
await using var inputDecompressor = new GZipStream(input, CompressionMode.Decompress, leaveOpen : true);
await using var outputCompressor = new GZipStream(output, CompressionMode.Compress, leaveOpen : true);
await using var outputBuffer = new BufferedStream(outputCompressor, BufferSize);
await using var writer = new Utf8JsonWriter(outputBuffer, new() { Indented = options.WriteIndented, Encoder = options.Encoder });
writer.WriteStartArray();
await foreach (var item in JsonSerializer.DeserializeAsyncEnumerable<TItem>(inputDecompressor, options))
JsonSerializer.Serialize(writer, item, options);
if (writer.BytesPending >= BufferSize)
await writer.FlushAsync();
foreach (var item in newItems)
JsonSerializer.Serialize(writer, item, options);
if (writer.BytesPending >= BufferSize)
await writer.FlushAsync();
public static async Task SerializeCompressedAsync<TValue>(string path, TValue value, JsonSerializerOptions? options = default)
using var output = File.OpenWrite(path);
await SerializeCompressedAsync(output, value, options);
public static async Task SerializeCompressedAsync<TValue>(Stream utf8Json, TValue value, JsonSerializerOptions? options = default)
await using var outputCompressor = new GZipStream(utf8Json, CompressionMode.Compress, leaveOpen : true);
await using var outputBuffer = new BufferedStream(outputCompressor, BufferSize);
await JsonSerializer.SerializeAsync<TValue>(outputBuffer, value, options);
public record SipTraceRecord(string name, string value);
public static async Task Test()
Console.WriteLine("Testing byte streaming");
Console.WriteLine("\nTesting file streaming");
static async Task TestByteArrays()
List<SipTraceRecord> initialList = Enumerable.Range(0, 10).Select(i => new SipTraceRecord("Byte Array Name " + i, "Value " + i)).ToList();
var options = new JsonSerializerOptions
await using (var output = JsonExtensions.MemoryStreamManager.GetStream())
await JsonExtensions.SerializeCompressedAsync(output, initialList, options);
initialBytes = output.ToArray();
List<SipTraceRecord> list = new(Enumerable.Range(10, 10).Select(i => new SipTraceRecord("Byte Array Name " + i, "Added " + i)));
var appendedBytes = await JsonExtensions.CopyAndAddToBCompressedyteArrayAsync(initialBytes, list, options);
await using (var input = new MemoryStream(appendedBytes))
await using (var inputDecompressor = new GZipStream(input, CompressionMode.Decompress))
using (var textReader = new StreamReader(inputDecompressor, Encoding.UTF8, leaveOpen : true))
var text = await textReader.ReadToEndAsync();
static async Task TestFiles()
var filePath = "Question79221507.json";
List<SipTraceRecord> initialList = Enumerable.Range(0, 10).Select(i => new SipTraceRecord("Name " + i, "Value " + i)).ToList();
var options = new JsonSerializerOptions
await JsonExtensions.SerializeCompressedAsync(filePath, initialList, options);
List<SipTraceRecord> addList = new(Enumerable.Range(10, 10).Select(i => new SipTraceRecord("Added " + i, "Added " + i)));
var tempPath = Path.GetTempFileName();
await JsonExtensions.CopyAndAddToCompressedFileAsync(filePath, tempPath, addList, options);
File.Move(tempPath, filePath, true);
await using (var input = File.OpenRead(filePath))
await using (var inputDecompressor = new GZipStream(input, CompressionMode.Decompress))
using (var textReader = new StreamReader(inputDecompressor, Encoding.UTF8, leaveOpen : true))
var text = await textReader.ReadToEndAsync();
public static async Task Main()
Console.WriteLine("Environment version: {0} ({1}), {2}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version, Environment.OSVersion);
Console.WriteLine("System.Text.Json version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");