JsonSerializer.DeserializeAsyncEnumerable async processing and torn JSON stream behaviour

702 views Asked by At

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?

1

There are 1 answers

0
McMurphy On BEST ANSWER

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);