Search code examples
c#dotnet-httpclientjson-deserializationsystem.text.jsoniasyncenumerable

JsonSerializer.DeserializeAsyncEnumerable async processing and torn JSON stream behaviour


Having had to solve the problem of iterating through the YEILDed results from a C# IAsyncEnumerable controller method myself with Javascript, by writing my own iterator to handle JSON tears, I was extolling the virtues of the C# JsonSerializer.DeserializeAsyncEnumerable method to the team as doing all the heavy lifting for us.

Then my tests show that: -

IAsyncEnumerable<SearchName?> resultNames = JsonSerializer.DeserializeAsyncEnumerable<SearchName>(outStream, opts, cancellationSource.Token);
await foreach (SearchName name in resultNames){
    Console.WriteLine(Uri.UnescapeDataString(name.familyName));
}

Won't start iterating until the entire buffer (resultNames) has been retrieved from the server and reassembled into an array by DeserializeAsyncEnumerable :-(

Do I have to write my own iterator and cater for tears in JSON chunks just like I did in Javascript?

Here at Github is a similar question. Sadly, when I follow the Bug Fix it says: -

"Fixes regression introduced by #51702: the ContinueDeserialize method will return 'null' on partial reads so no elements will be yielded by the enumerator until the entire stream has been consumed."

My question is how can I make JsonSerializer.DeserializeAsyncEnumerable (or use another C# strategy) start returning the Enumerable content Asynchronously as soon as it is available as a partial result?


Solution

  • Sorry, found the answer on the next search link

    TLDR; The buffer size controls the behaviour:

    IAsyncEnumerable<SearchName?> resultNames = JsonSerializer.DeserializeAsyncEnumerable<SearchName>(
        outStream, 
        new JsonSerializerOptions { 
            DefaultBufferSize = 100, //** Set this value
            AllowTrailingCommas = true }, 
        cancellationSource.Token);