I am trying to pull JSON data from a website and I am having some trouble iterating over the objects it returns. Can someone please assist with navigating this structure? I am confused by it not being uniform.
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "myToken");
httpClient.BaseAddress = new Uri("https://app.website.com/data/");
HttpResponseMessage response = httpClient.GetAsync("getData.json?item=myItem").Result;
response.EnsureSuccessStatusCode();
dynamic result = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
Console.WriteLine("Result: " result);
dynamic jsonArray = result.results;
foreach (var item in jsonArray.items)
{
Console.WriteLine(item.date1);
}
}
The JSON array I'm dealing with is below. My goal is to iterate through item
and get all of the date1
and date2
values. I don't need anything else.
{
"results": {
"copyright": "Copyright",
"items": [{
"info": {
"longname": "XXX",
"shortname": "YYY"
},
"item": [{
"date1": "2022-01-01",
"date2": "2022-01-05",
}, {
"date1": "2022-04-01",
"date2": "2021-04-07",
}],
"key": {
"keyName": "AAA",
"keySym": "BBB",
},
"symString": "BBB"
}],
"count": 1
}
}
CodePudding user response:
You are making extra work for yourself by using dynamic
as you lose IntelliSense as well as compile-time type checking. The underlying type returned by Json.NET for dynamic
will typically be some subtype of JToken
, so the easiest way to accomplish your task is to deserialize to JToken
and use SelectTokens()
like so:
var result = JsonConvert.DeserializeObject<JToken>(jsonString);
var dates = result.SelectTokens("results.items[*].item[*]")
.Select(i => new { date1 = i["date1"].ToObject<DateOnly>(), date2 = i["date2"].ToObject<DateOnly>() });
foreach (var item in dates)
{
Console.WriteLine($"Date1={item.date1}, Date2={item.date2}.");
}
Which prints
Date1=01/01/2022, Date2=01/05/2022.
Date1=04/01/2022, Date2=04/07/2021.
Notes:
The query string
"results.items[*].item[*]"
passed toSelectTokens()
is a JSONPath query that includes wildcards to select all items in the"items"
array and the nested"item"
array.DateOnly
was introduced in .NET 6. In earlier versions useDateTime
.Using
httpClient.GetAsync(url).Result
can sometimes cause deadlocks, see An async/await example that causes a deadlock for details. If this happens, consider converting your code to be asynchronous, or see What's the "right way" to use HttpClient synchronously?.
Demo fiddle here