dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.24k stars 4.73k forks source link

`JsonSerializer.DeserializeAsyncEnumerable` should support streaming from nested JSON arrays. #101446

Open Sonic198 opened 6 months ago

Sonic198 commented 6 months ago

Hello, I'm using HttpClient to integrate with an API which returns data in following format

{
  "eventList": [
    {
      "eventType": "RECEIVED",
      "houseAirWaybill": "AMZ-20240006",
      "iataCode": "SEA",
      "icaoCode": "KSEA",
      "localDatetime": "2024-03-19T10:59:07.908-07:00",
      "localTimezone": "America/Los_Angeles",
      "shipmentType": "CONTAINER",
      "zuluDatetime": "2024-03-19T17:59:07.908Z"
    }
  ]
}

It is possible to have hundreds or even thousands of events inside eventList so since now we can use ReadFromJsonAsAsyncEnumerable<TValue> I was wondering if it would be possible to somehow iterate through that objects in eventList array without a need of loading all of them into memory?

Tornhoof commented 6 months ago

Are you aware of https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializer.deserializeasyncenumerable ?

Sonic198 commented 6 months ago

@Tornhoof but how that would be usable in that case?

Are you aware of https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializer.deserializeasyncenumerable ?

Tornhoof commented 6 months ago

It depends on the exact structure of your json response. If your array is nested inside another object it won't help.

The reasoning for only root-level IAsyncEnumerable support is here https://github.com/dotnet/runtime/issues/1570#issuecomment-804355005

dotnet-policy-service[bot] commented 6 months ago

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis See info in area-owners.md if you want to be subscribed.

Sonic198 commented 6 months ago

It depends on the exact structure of your json response. If your array is nested inside another object it won't help.

The reasoning for only root-level IAsyncEnumerable support is here #1570 (comment)

Yeah so as you can see in first post I unfortunately gets one object with nested array of objects in it so I guess there is no easy way of utilizing IAsyncEnumerable to deserialize those data.

eiriktsarpalis commented 6 months ago

This is a known restriction of the DeserializeAsyncEnumerable methods. In principle it should be possible to expose new overloads that additionally accept a JSON path value pinpointing an entry point for the streamed array, in your example:

JsonSerializer.DeserializeAsyncEnumerable<Event>(utf8Stream, path: "$.eventList"); 

We would need to add corresponding overloads to System.Net.Http.Json as well.