The point of the program is to find the total number of films a character has been a part of.
I'm trying to access a Newtonsoft.Json.Linq.JArray type object to count the length of a multidimensional array.
Json array:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"name": "Luke Skywalker",
"height": "172",
"mass": "77",
"hair_color": "blond",
"skin_color": "fair",
"eye_color": "blue",
"birth_year": "19BBY",
"gender": "male",
"homeworld": "descriptiontext",
"films": [
"linkapifilms1",
"linkapifilms2",
"linkapifilms3",
"linkapifilms6",
"linkapifilms7"
],
"species": [],
"vehicles": [
"linapivehicles14",
"linapivehicles30"
],
"starships": [
"linapistarships12",
"linapistarships22"
],
"created": "2014-12-09T13:50:51.644000Z",
"edited": "2014-12-20T21:17:56.891000Z",
"url": "linkapipeople1"
}
]
}
I'm trying to access "films": to count the length of the array and store/display it on an int variable.
My Code:
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class Solution
{
static void Main()
{
Console.WriteLine("Number of films: " + Run("Luke Skywalker"));
Console.ReadKey();
}
static public int Run(string character)
{
int numberOfFilms = 0;
Task<string> result = GetResponseString(character);
var jsonResult = result.Result;
dynamic dynamicResultObject = JsonConvert.DeserializeObject(jsonResult);
JArray x = dynamicResultObject.results;
//Find length of "films" code insert//
Console.WriteLine(character);
return numberOfFilms;
}
static public async Task<string> GetResponseString(string character)
{
var httpClient = new HttpClient();
var response = await httpClient.GetAsync("linktoapi/api/people/?search=" + character);
var contents = await response.Content.ReadAsStringAsync();
return contents;
}
}
I can access the first line of array with dynamicResultObject.results;
So the question is how do I access films, which is inside results and find the length?
Edit: I understand that this may not be the best way to go about writing this program however, is it not possible to just access the child array of the main array with the current code?
First of all, I would advise against using dynamic as it will just cause you headaches. If you're going to work with JObjects and JArrays anyway you're better off just using those types directly. The compiler will be able to detect errors earlier and you will get the Intellisense help in Visual Studio. So, parse your JSON like this:
JObject rootObject = JObject.Parse(jsonResult);
From that you can get your results array. (You were calling this array x in your code, but I think resultsArray is a more descriptive variable name):
JArray resultsArray = (JArray)rootObject["results"];
Like any array, if you want to get at a particular element you need to use its index. We can get the first element of the array (which is the object containing Luke Skywalker's data) like this:
JObject characterObject = (JObject)resultsArray[0];
From there, you can get the films property, which is also a JArray:
JArray filmsArray = (JArray)characterObject["films"];
To get the length of a JArray you use the Count property:
numberOfFilms = filmsArray.Count;
Fiddle: https://dotnetfiddle.net/iFAWB4
Now that you know how to drill down through the objects and arrays step-by-step, I'll show you a little shortcut, the SelectToken() method. This method allows you to specify a "path" to get a particular JToken (JObject and JArray are both types of JTokens). So, after parsing your JSON, you could get the films array directly like this:
JArray filmsArray = (JArray)rootObject.SelectToken("results[0].films");
and then get its count just like before.
Fiddle: https://dotnetfiddle.net/zOdSFs
Related
I can´t find a value in a json string using json.net
I´ve tried jsonstr[0].track_numbers[0].track_number
This is my json file.
{
"0": {
"increment_id": "112",
"track_numbers": [
{
"track_number": "2223",
"title": "tit",
"carrier_code": "custom"
}
]
},
"live_shipping_status": "Delivered"
}
I want to find the Track_nummber.
dynamic jsonstr = JsonConvert.DeserializeObject(json));
var track = jsonstr[0].track_numbers[0].track_number
(donsent work)
The 0 of your json is a string key, not an index position:
dynamic obj = JsonConvert.DeserializeObject(json);
var trackNumber = obj["0"].track_numbers[0].track_number;
Note the difference in getting the first entry of track_numbers, which is an array.
I have a Json string like below and this is only a small snippet. The number in quotation marks is a Unix Time which i will need to use to iterate over each object.
{
"result": {
"1534860000": [
"1534860000",
19,
41
],
"1534863600": [
"1534863600",
11,
16
],
"1534867200": [
"1534867200",
2,
5
]
}
}
But when I attempt to extract the data in the arrays I get an error:
System.InvalidOperationException: 'Cannot access child value on Newtonsoft.Json.Linq.JProperty.'
Code:
JObject jsonObj = JObject.Parse(response);
string unixTime = Helpers.ConvertToUnix(yesterday.AddHours(hour)).ToString();
foreach (var obj in jsonObj["result"])
{
var array = obj[unixTime]; //here is where the error occurs
}
Anyone able to shed some light on what I am missing?
If we simplify your example code a little to remove the unixTime element (let's just hardcode it for now), we end up with this:
JObject jsonObj = JObject.Parse(response);
string unixTime = "1534860000";
At this stage, we have jsonObj which refers to the root of the JSON object and has a single property of result. Repeating your foreach here for context:
foreach (var obj in jsonObj["result"])
{
var array = obj[unixTime]; //here is where the error occurs
}
You end up with obj referring to the JSON path of result.1534860000. The problem is you're then looking for a property 1534860000 at this JSON path (result.1534860000.1534860000), which does not exist.
You can just get the value directly, like so:
var array = obj["result"][unixTime]
Of course, this requires some error-checking for ensuring the path exists, etc, but it demonstrates the point.
After some help from Kirk Larkin I thought I would post a code snippet up.
JObject jsonObj = JObject.Parse(response);
int hour = 0;
string unixTime = Helpers.ConvertToUnix(yesterday.AddHours(hour)).ToString();
var array = jsonObj["result"][unixTime];
It now returns the contents of the array.
I have been building an application where JSON will be provided from a user API. It should read the data from the JSON using JSONPath and persist the selected portions. I am trying to do this using Json.Net (Newtonsoft). The following JSON is a sample:
{
// other properties here and different structure here
"Data": [
{
"Code": "625087",
"Name": "Customer Name",
"Email": "test#hfgidfgd.com"
},
{
"Code": "625087",
"Name": "Customer Name",
"Email": "test#hfgidfgd.com"
},
{
"Code": "625087",
"Name": "Customer Name",
"Email": "test#hfgidfgd.com"
}
],
// other properties here and different structure here
}
I would like to extract the array presented by the Data property content using JSONPath and convert it to List<Dictionary<string, object>> to manipulate in my application.
In tools like jsonpath.com the following JSONPath query works fine but with Newtonsoft it does not:
// get that json
string content = GetJson();
var jo = JObject.Parse(content);
var jsonPath = "$..Data.*";
var jsonPathResult = jo.SelectTokens(jsonPath, true /* to get error when it is not found */ );
Instead I got the exception:
Property '*' not valid on JArray.
If I do the JSONPath like this:
var jsonPath = "$..Data"; // same for just: "Data"
var jsonPathResult = jo.SelectTokens(jsonPath);
I have to loop on the result with two nested foreach, what I think it is not an elegant solution:
var result = new List<Dictionary<string, object>>();
foreach (var jsonResult in jsonPathResult)
{
foreach (var item in jsonResult)
{
var fields = JsonConvert.DeserializeObject<Dictionary<string, object>>(item.ToString());
// some adjusts on the fields dictionary will be applied here...
result.Add(fields);
}
}
Is there any way to get the result to take a single loop the only the content of Data property?
As shown in JSONPath - XPath for JSON, the syntax for an array element wildcard is [*]. Thus your code should look like:
var jsonPath = "$..Data[*]";
var result = jo.SelectTokens(jsonPath, true /* to get error when it is not found */ )
.Select(o => o.ToObject<Dictionary<string, object>>())
.ToList();
Here I am using JToken.ToObject<T>() to deserialize each array element directly to a Dictionary<string, object>> without re-serializing to a string.
Sample working .Net fiddle.
Lets say I get the following json data from a web service which I can't change.
[
[
"Header1",
"Header2",
"Header3",
"Header4"
],
[
"FirstValue1",
"FirstValue2",
"FirstValue3",
"FirstValue4"
],
[
"SecondValue1",
"SecondValue2",
"SecondValue3",
"SecondValue4"
]
]
jsonlint.com tells me that it is valid json and from what I know I would agree.
But somehow I'm wondering is there any "easy" way to deserialize this to a class. Each of the values in the second and third array belongs to the corresponding header in the first array.
I know how to use Json.NET but can't get my head around on how to use it with this data structure.
Simple - you can use JsonConvert.DeserializeObject to deserialize it to a string[][]:
using System;
using System.IO;
using Newtonsoft.Json;
class Test
{
static void Main()
{
var json = File.ReadAllText("test.json");
string[][] array = JsonConvert.DeserializeObject<string[][]>(json);
Console.WriteLine(array[1][3]); // FirstValue4
}
}
The easiest way is to use the string class and deserialzie it using Json.NET.
string[][] values = JsonConvert.DeserializeObject<string[][]>(json);
A better option could be to use
using Newtonsoft.Json.Linq
string json = #"{
CPU: 'Intel',
Drives: [
'DVD read/writer',
'500 gigabyte hard drive'
]
}";
JObject o = JObject.Parse(json);
string CPU = o.CPU;
int NumDrives = o.Drives.Count;
Source: http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Linq_JObject_Parse.htm
I'm try to parse some JSON like this:
{
"results": [
"MLU413843206",
"MLU413841098",
"MLU413806325",
"MLU413850890",
"MLU413792303",
"MLU413843455",
"MLU413909270",
"MLU413921617",
"MLU413921983",
"MLU413924015",
"MLU413924085"
]
}
All is fine until I try to obtain the values themselves, for example:
// The JSON is shown above
var jsonResp = JObject.Parse(json);
var items = jsonResp["results"].Children();
I don't know how to obtain the values, each converted to string. Does somebody know how to do this?
You're halfway there. You can use the Select() method in the System.Linq namespace to project the IEnumerable<JToken> returned from the Children() method into an IEnumerable<string>. From there you can loop over the values using foreach, or put the values into a List<string> using ToList() (or both).
string json = #"
{
""results"": [
""MLU413843206"",
""MLU413841098"",
""MLU413806325"",
""MLU413850890"",
""MLU413792303"",
""MLU413843455"",
""MLU413909270"",
""MLU413921617"",
""MLU413921983"",
""MLU413924015"",
""MLU413924085""
]
}";
JObject jsonResp = JObject.Parse(json);
List<string> items = jsonResp["results"].Children()
.Select(t => t.ToString())
.ToList();
foreach (string item in items)
{
Console.WriteLine(item);
}
Fiddle: https://dotnetfiddle.net/Jcy8Ao