Home > front end >  Large JSON file
Large JSON file

Time:06-02

I have large json files and I need to return them from Web API using .NET 6. Some metadata should be added, so the DTO looks like this

public class Response
{
  public int Id { get; set; }
  public T Content { get; set; }
}

Tried to use Utf8JsonWriter, no luck. It doesn't have api to write stream. Is there a way to stream file without allocationg it in memory?

await using var writer = new Utf8JsonWriter(Response.Body, new JsonWriterOptions{SkipValidation = true});
writer.WriteStartObject();
writer.WriteNumber("Id", 1);
writer.WritePropertyName("Content");
writer.WriteRawValue(GetStream(filePath));  // there is a way to do this?

await writer.FlushAsync();

CodePudding user response:

You can either fully buffer the file into a byte array and write that using WriteRawValue

await using var writer = new Utf8JsonWriter(Response.Body, new JsonWriterOptions{SkipValidation = true});
writer.WriteStartObject();
writer.WriteNumber("Id", 1);
writer.WritePropertyName("Content");

await using var file = GetStream(filePath);
var buffer = new byte[file.Length];
using (var memoryStream = new MemoryStream(buffer))
await file.CopyToAsync(memoryStream);
writer.WriteRawValue(buffer, true);
writer.WriteEndObject();
await writer.FlushAsync();

Or you can stream it in. You cannot use WriteRawValue for this, as it requires a single value. Even with SkipValidation, it will mess up the state of the writer, so you need to write the property name and the value directly to the underlying stream.

await using var writer = new Utf8JsonWriter(Response.Body, new JsonWriterOptions{SkipValidation = true});
writer.WriteStartObject();
writer.WriteNumber("Id", 1);
await writer.FlushAsync();  // you MUST flush the JSON writer first
await Response.Body.WriteAsync(Encoding.UTF8.GetBytes(@"""Content"":"));
var buffer = new byte[4096];
await using var file = GetStream(filePath);
await file.CopyToAsync(Response.Body);
writer.WriteEndObject();
await writer.FlushAsync();
  • Related