Flurl icon indicating copy to clipboard operation
Flurl copied to clipboard

Support json path in GetJsonAsync/ReceiveJson methods.

Open voroninp opened this issue 5 years ago • 5 comments

Some APIs return payloads which contain more than API consumer may need at the moment.

Fore example Pipedrive SaaS when queried for products returns :

{
    "success": true,
    "data": [...],
    "additional_data": {...},
    "related_objects": {...}
}

Therefore it would be nice to have an overload for GetJsonAsync to get only some part of payload:

await "some url".GetJsonAsync<T>("$.data");

voroninp avatar Jan 14 '19 15:01 voroninp

Thanks for the suggestion. I like the idea, but I think it's duplicate of #218 (see my comments there). It's been on the roadmap for quite a while. It'll likely be a 3.0 thing, since it probably has breaking implications.

In the mean time, you could just define a class that only has the data property so the other stuff gets discarded on deserialization. I know that's not as good, but it's easier than defining the whole structure.

tmenier avatar Jan 14 '19 20:01 tmenier

Yes, it's the same. However, I'd offer to consider one additional thing.

Flurl reads stream only once and then disposes it as I can see. The above mentioned PipeDrive API returns pagination info along with data:

{
   "data": [...],
   "additional_data": {
        "pagination": {
            "start": 0,
            "limit": 100,
            "more_items_in_collection": false
        }
    }
}

So I deserialize response first as JObject and then extract both data and pagination info. In other words, it might be useful to be able to extract multiple parts of a payload, not just single element.

voroninp avatar Jan 14 '19 21:01 voroninp

@voroninp To be honest I don't think I'd support getting multiple objects of different types. You'd need to provide a type and path for each object you want, and some way to return multiple objects. Imagine what the method signature would look like - a bit ugly I think. I imagine I'll support passing a single type and path (like you proposed originally) and getting back a single object or collection.

For your PipeDrive example, I think defining a matching class and just leaving out the properties you don't need is the way to go. Another option is to call GetJsonAsync() without a type arg and you'll get back a dynamic, which might be easier to traverse and pick out the parts you want than a JObject.

tmenier avatar Jan 20 '19 15:01 tmenier

I closed #218 in favor of this issue because it's closer to what I want to do. As noted there, this should be useful:

https://www.newtonsoft.com/json/help/html/SelectToken.htm

Also as noted, need to evaluate whether the ability to swap out NewtonsoftJsonSerializer for something else could complicate this in any way.

tmenier avatar Jan 20 '19 15:01 tmenier

I'm actively gathering feedback to help prioritize issues for 3.0. If this one is important to you, please vote for it here!

tmenier avatar Apr 06 '19 14:04 tmenier