I am selecting a json object as follows:
var gridRenderer = json.SelectToken("$..gridRenderer").FirstOrDefault();
The line above gives the following subset of the JSON shown at the end of the question:
{
"items": [
{
"gridVideoRenderer": { } // Many properties omitted.
},
// Other entries omitted.
Located at the path:
contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.sectionListRenderer.contents[0].itemSectionRenderer.contents[0].gridRenderer
As you can see above there is a lot of data. I want to cast this to typed object with a sub set of properties:
var ee = gridRenderer.Cast<GridRenderSection>();
First I just wanted to get an array with objects with the videoid. I have following classes:
[JsonObject("gridRenderSection")]
public class GridRenderSection
{
[JsonProperty("items")]
public List<GridVideoRenderer> Items{ get; set; }
}
public class GridVideoRenderer
{
[JsonProperty("videoId")]
public string VideoId { get; set; }
}
But I get following error: "Unable to cast object of type 'Newtonsoft.Json.Linq.JArray' to type 'GridRenderSection'."
Normally you can cast subset of types objects, is that not possible with the Cast function, or am I missing something here?
Sample code (notice you can see json on the link provided in sample code or below):
var jsonStr = string.Empty;
using (WebClient client = new WebClient())
{
jsonStr = client.DownloadString("https://srv-file2.gofile.io/download/J1iBAd/json1.json");
}
var json = JObject.Parse(jsonStr);
var gridRenderer = json.SelectToken("$..gridRenderer").FirstOrDefault();
var ee = gridRenderer.Cast<GridRenderSection>();
JSON:
{
"contents": {
"twoColumnBrowseResultsRenderer": {
"tabs": [
{
"tabRenderer": {
"title": "Videoer",
"selected": true,
"content": {
"sectionListRenderer": {
"contents": [
{
"itemSectionRenderer": {
"contents": [
{
"gridRenderer": {
"items": [
{
"gridVideoRenderer": {
"videoId": "lzSlEtuHgAU"
}
},
{
"gridVideoRenderer": {
"videoId": "F5Opl1llzWw"
}
}
]
}
}
]
}
}
]
}
}
}
}
]
}
}
}
You have a few problems here:
Your query json.SelectToken("$..gridRenderer")
is returning a single JToken
corresponding to the following JSON object:
{ "items": [ { "gridVideoRenderer": { "videoId": "lzSlEtuHgAU" } }, { "gridVideoRenderer": { "videoId": "F5Opl1llzWw" } } ] }
You are trying to cast this to a GridRenderSection
, but JToken
has no explicit or implicit type conversion to arbitrary types -- only to simple IConvertible
types. Instead you will need to deserialize to GridRenderSection
using ToObject<GridRenderSection>()
:
var ee = gridRenderer.ToObject<GridRenderSection>();
You are calling FirstOrDefault()
on the return from SelectToken()
:
json.SelectToken("$..gridRenderer").FirstOrDefault();
However, SelectToken()
already returns a single JToken
that matches the query, in this case a JObject
. (If there is more than one match, SelectToken()
throws an exception.) Later, when you do .FirstOrDefault()
you are grabbing the first property of the object and trying to deserialize that single property into your data model, which is wrong.
Generally, if you are calling SelectToken()
there is no need to call .FirstOrDefault()
; it's more commonly applied to SelectTokens()
when there might be many matches and only the first is needed.
Your data model does not match your JSON. videoId
is nested inside a container object gridVideoRenderer
which needs to be modeled like so:
public class GridRenderSection { [JsonProperty("items")] public List<GridRenderSectionItem> Items{ get; set; } } public class GridRenderSectionItem { public GridVideoRenderer gridVideoRenderer { get; set; } } public class GridVideoRenderer { [JsonProperty("videoId")] public string VideoId { get; set; } }
Incidentally, if all you need are the videoId
values, you could use the following SelectTokens()
query to extract them directly:
var videoIds = json.SelectTokens("$..gridRenderer.items[*].gridVideoRenderer.videoId")
.Select(t => t.ToString())
.ToList();
Or if you want just a list of GridVideoRenderer
objects:
var renderers = json.SelectTokens("$..gridRenderer.items[*].gridVideoRenderer")
.Select(t => t.ToObject<GridVideoRenderer>())
.ToList();
Demo fixed fiddle here .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.