Parsing JSON list to int array in c# - c#

I'm having trouble reading a JSON list of numbers into a c# int[] array.
I've tried several suggestions from SO, but none have worked.
How would I go about this using JSON.net?
Extract from JSON file:
{
"course": "Norsk",
"grades": [6, 3, 5, 6, 2, 8]
}
What I've tried in c#:
// Reads the JSON file into a single string
string json = File.ReadAllText(jfile);
Console.WriteLine(json);
// Parsing the information to a format json.net can work with
JObject data = JObject.Parse(json);
JToken jToken = data.GetValue("grades");
jGrades = jToken.Values<int>().ToArray();
and:
// Reads the JSON file into a single string
string json = File.ReadAllText(jfile);
Console.WriteLine(json);
// Parsing the information to a format json.net can work with
JObject data = JObject.Parse(json);
for (int o = 0; o < 6; o++) {
var grades = from p in data["Info"[i]] select (int)p["grades"[o]];
jGrades.Add(Convert.ToInt32(grades));
}
As you can see from the c# extracts, I've tried with both arrays and lists, but I can't get it to work.
With the first example (with an array) I get a System.NullRefrenceException, while with the List example, I get several errors, such as Unable to cast object of type 'whereselectlistiterator'2 [Newtonsoft.JSON] to type 'system.iconvertible'
Any help of tips are appreciated.

JObject.Parse(json) is your root object
JObject.Parse(json)["grades"] is the list/array
All you have to do is : converting the items to appropriate type
var list = JObject.Parse(json)["grades"].Select(x => (int)x).ToArray();
You can also declare a class
public class RootObject
{
public string course { get; set; }
public List<int> grades { get; set; }
}
and deserialize whole object as
var myobj = JsonConvert.DeserializeObject<RootObject>(json);
var grade = myobj.grades[0];

I would typically define a class with the relevant properties and simply convert the object.
public class CourseReport
{
public string Course { get; set; }
public ICollection<int> Grades { get; set; }
}
// Reads the JSON file into a single string
string json = File.ReadAllText(jfile);
Console.WriteLine(json);
// Parsing the information to a format json.net can work with
var courseReport = JsonConvert.DeserializeObject<CourseReport>(json);
foreach (var grade in courseReport.Grades)
{
Console.WriteLine(grade);
}

Related

Is there a way to deserialize only a single JSON field [duplicate]

So I have a JSON string where I just want to read a specific value. How do I just pick "Read me please!" from string below?
var readString = /*Read me please!*/
JSON string:
"{\"aString\":\"Read me please!\"}"
For better understanding, how do I do the same here? (just "Read me please!"):
"{\"Result\":
{
\"aString\":\"Read me please!\",
\"anotherString\":\"Dont read me!\"
}
}"
If both alternative have different solution I would like to know both.
PS: I do not wish to save the value into object/class or so. Just temporary inside var readString.
You could write a model:
public class MyModel
{
public string AString { get; set; }
}
and then use a JSON serializer such as Json.NET:
string readString = "{\"aString\":\"Read me please!\"}";
MyModel model = JsonConvert.DeserializeObject<MyModel>(readString);
Console.WriteLine(model.AString);
If you don't want to use third party solutions you could use the built-in JavaScriptSerializer class:
string readString = "{\"aString\":\"Read me please!\"}";
MyModel model = new JavaScriptSerializer().Deserialize<MyModel>(readString);
Console.WriteLine(model.AString);
Now assuming you want to handle your second JSON string you could simply adapt your model:
public class Wrapper
{
public MyModel Result { get; set; }
}
public class MyModel
{
public string AString { get; set; }
public string AnotherString { get; set; }
}
and then deserialize to this wrapper class:
string readString = ... the JSON string in your second example ...;
Wrapper wrapper = JsonConvert.DeserializeObject<Wrapper>(readString);
Console.WriteLine(wrapper.Result.AString);
Console.WriteLine(wrapper.Result.AnotherString);
UPDATE:
And if you don't want to deserialize to a model you could directly do this:
string readString = "{\"aString\":\"Read me please!\"}";
var res = (JObject)JsonConvert.DeserializeObject(readString);
Console.WriteLine(res.Value<string>("aString"));
or with the built-in JavaScriptSerializer class:
string readString = "{\"aString\":\"Read me please!\"}";
var serializer = new JavaScriptSerializer();
var res = (IDictionary<string, object>)serializer.DeserializeObject(readString);
Console.WriteLine(res["aString"]);
var readString = JObject.Parse(str)["aString"];
Or for your second example:
var readString2 = JObject.Parse(str2)["Result"]["aString"];
Json.NET also provides a JSON reader if you don't want to deserialize the whole thing. For example:
string json = "{\"Result\": { \"aString\":\"Read me please!\", \"anotherString\":\"Dont read me!\" } }";
using (var reader = new JsonTextReader(new StringReader(json)))
{
while (reader.Read())
{
if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "aString")
{
reader.Read();
Console.Write(reader.Value);
break;
}
}
}
Console.ReadKey();
You have to use Newtonsoft (JSON.NET) to accomplish that. Then, you can access your json property this way:
var obj = JsonConvert.DeserializeObject(yourJson);
Console.WriteLine(obj.Result.aString);
I played around with writing a generic method that can read any part of my json string. I tried a lot of the answers on this thread and it did not suit my need. So this is what I came up with. I use the following method in my service layer to read my configuration properties from the json string.
public T getValue<T>(string json,string jsonPropertyName)
{
var parsedResult= JObject.Parse(json);
return parsedResult.SelectToken(jsonPropertyName).ToObject<T>();
}
and this is how you would use it :
var result = service.getValue<List<string>>(json, "propertyName");
So you can use this to get specific properties within your json string and cast it to whatever you need it to be.

Deserialize JSON Data into a List in C#

After hours of searching and trying, can someone please be so kind and help me solving this following simple problem:
I have the following JSON-String:
[
{
"key": 1234,
},
{
"key": 9876,
}
]
How can I read this JSON and write all values into a List?
Had many attempts so far, but please see following code:
List<int> content = new List<int>;
var json = reader.ReadToEnd();
var obj = JObject.Parse(json);
First try:
foreach(var key in obj)
{
content.Add((int)obj["key"]);
}
Other try:
var token = obj.SelectToken("key");
foreach(var item in token)
{
content.Add(JsonConvert.DeserializeObject<int>(item.value));
}
Or something this way?
foreach(var key in obj)
{
content.Add(Int32.Parse(obj.GetValue("key").ToString()));
}
Trying to run the last attempt, I get following error message:
Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray.
Even if the JSON looks like the following:
[{\"key\":9999},{\"key\":9876}]
Would be very happy for every answer.
Best regards
Use Newtonsoft.Json
It can be done in the following way:
List<string> yourList = JsonConvert.DeserializeObject(YourJson).ToList();
NOTE: It can only be saved as a list of strings , but can be called with: yourList.YourKeyName.
Depends on what you want but you could also create a specified class for your json.
The following class represents your json string.
public class RootObject
{
public int key { get; set; }
}
You could then deserialise your json string as follows:
string json=reader.ReadToEnd();
List<RootObject> myobs=JsonConvert.DeserialiseObject<List<RootObject>>(json);
You can then do stuffs with the list.
foreach(var ob in myobs){
Console.WriteLine(ob.key);
}
Following on to what #bolkay said, you need to define your object:
public class KeyClass
{
public int Key { get; set; }
}
and then if your JSON is in a variable called jsString for example
List<int> content = new List<int>();
var keys = JsonConvert.DeserializeObject<List<KeyClass>>(jsString);
foreach (var item in keys)
{
content.Add(item.Key);
}

Unable to deserialize Json string array of arrays into object when using Newtonsoft.Json

i am using Newtonsoft.Json and trying to deserialize an array of arrays Json string into C# object i created.
This is the json string -
[4615,4618,4619,4626,4615,4626,4631,4636,4637],[4615,4618,4619,4626,4615,4626,4631,4636,4637],[4615,4618,4619,4626,4615,4626,4631,4636,4637]
This is my object model -
public class NumberMatrix
{
public List<int> NumberIDs { get; set; }
public NumberMatrix()
{
this.NumberIDs = new List<int>();
}
}
This is how i try to convert -
var numbers = HttpContext.Current.Request.Params["Numbers"];
var numberIDsMatrix = JsonConvert.DeserializeObject<List<NumberMatrix>>(numbers);
i tried to deserialize the json in few ways, and got different errors. is it possible to deserialize this json string? how?
That isn't valid JSON, you need to surround it with [...] for example. You could do this:
var result = JsonConvert.DeserializeObject<List<List<int>>>($"[{numbers}]");

Can't get data from deserialized Json string

I am really confused as to why I can't access any data that I have deserialized from Json string. When I step through the process I can see that the data is there, I just can't access it.
I am placing the data into Dictionary<string, object>, it's Count is 2. It contains object{object[]} (which I read as an ArrayList of objects?), and an object with response information.
I'm not too fussed about the response information I need to access the objects in the ArrayList. I'm having no such luck, my code is below:
var output = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(await response.Content.ReadAsStringAsync());
I have tried to get just the ArrayList using output["List"] (List is the objects key) and can still see all of the objects inside but still can't access them. It's probably a simple fix, it always is, but I have been staring at this problem all day and just can't make sense of it so could do with another pair of eyes.
Thanks
EDIT
The Json string is in the following format:
{"List":[{"Id":1,"intProperty":2,"boolProperty":false},{"Id":2,"intProperty":3,"boolProperty":false},{"Id":4,"intProperty":5,"boolProperty":false}],"ResponseInformation":{Other info here}}
Deserialize it into a class:
public class ListClass
{
public int Id;
public int IntProperty;
public bool boolProperty;
}
and then
var output = new JavaScriptSerializer().Deserialize<Dictionary<string, ListClass>>(await response.Content.ReadAsStringAsync());
And that should work!
I have figured out a long winded way of getting the information I need, If anyone can see a way to condense the code I'm open to suggestions :)
First I created my Currency class
public class Currency
{
public int CurrencyId { get; set; }
public int GlobalCurrencyId { get; set; }
public bool Archived { get; set; }
}
Next I deserialized my Json as I did in my question
var output = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(await response.Content.ReadAsStringAsync());
Next is the long winded bit; I used a foreach statement to get each element of my output variable. It was then made clear that the data inside was an array of dictionary objects so I created a list of Currency class objects:
var currencyObject = output["List"];
List<Currency> currencyList = new List<Currency>();
Currency item;
ArrayList myList = currencyObject as ArrayList;
foreach (object element in myList)
{
Dictionary<string, object> L1 = element as Dictionary<string, object>;
item = new Currency();
item.CurrencyId = Convert.ToInt32(L1["CurrencyId"]);
item.GlobalCurrencyId = Convert.ToInt32(L1["GlobalCurrencyId"]);
item.Archived = Convert.ToBoolean(L1["Archived"]);
currencyList.Add(item);
}
Figured it out in just two lines!!
var json = response.Content.ReadAsStringAsync().Result;
IList<Currency> output = new JsonSerializer().Deserialize<IList<Currency>>(new JsonTextReader(new StringReader(json)));

Separating array and element from a JSON string

I am connecting you Google Places API to retrive results in the form of a JSON string. You can view the complete format of the string Here.
If you a look at it you will see that the actual results array starts after two elements which are html_attributions and next_page_token.
So When i try to deserialize it in this way:
var serializer = new JavaScriptSerializer();
var arr= serializer.Deserialize(result,typeof(string[]));
I get an empty array.
My question is how is there a way i can separate html_attributions and next_page_token fields and the pass the valid results array from the string to be deserialized?
I don't understand the part where you wish to seperate the html_attributions and the next_page_token.
Wouldn't it be sufficient to just deserialize the response with whatever properties that you need?
For example, you can deserialize the response to only retrieve the values that you desire;
// I represent the wrapper result
class Result
{
public List<string> html_attributions { get; set; }
public string next_page_token { get; set; }
public List<ResultItem> results { get; set; }
}
// I represent a result item
class ResultItem
{
public string id { get; set; }
public string name { get; set; }
}
// the actual deserialization
Result Deserialize(string json)
{
var serializer = new JavaScriptSerializer();
return serializer.Deserialize(json, typeof(Result));
}
Edit:
The reason that your deserialization doesn't return you a array of strings is because the response that you retrieve is infact an object and not an array, however the parameter within that object which is named results is an array. In order for you to deserialize more properties you'll have to define them in your "ResultItem" class, sorry for my poor naming here.
For instance, if you'd wish to also retrieve the icon property per result you'll have to add a property named "icon" of type string.
Meanwhile the property "photos" is an array, in order to deserialize it you'll have to create another class and add a property of type list/array of that newly created class, and it has to be named "photos" unless you use a different serializer or use DataContract and DataMember attributes (using the Name property for field mapping).
// the representation of a photo within a result item
class Photo
{
public int height { get; set; }
public List<string> html_attributions { get; set; }
public string photo_reference { get; set; }
public int width { get; set; }
}
// I represent a result item
class ResultItem
{
public string id { get; set; }
public string name { get; set; }
// the added icon
public string icon { get; set; }
// the added photos collection, could also be an array
public List<Photo> photos { get; set; }
}
Just look at the JSON result to figure out what other properties that you might want to add, for instance the "scope" property is an string whilst the "price_level" is an integer.
If I understand your comment correctly you're only interested in the actual results, you'll still have to deserialize the response correctly with its wrapper.
// the actual deserialization
List<ResultItem> Deserialize(string json)
{
var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize(json, typeof(Result));
return result.results;
}
Edit2:
If you really want a string[] as a result you could simply take use of System.Linq using the code above.
string[] stringArray = result.results.Select(r => string.Format("id:{0} - name:{1}", r.id, r.name)).ToArray();
Edit3:
Instead of using the JavascriptSerializer you could use JObject functionality which can be found in the Newtonsoft.Json.Linq library.
var jsonObject = JObject.Parse(json);
string[] results = jsonObject.SelectTokens("results").Select(r => r.ToString()).ToArray();
This will give you an array of strings where each value within the array is the actual json string for each result.
If you however would like to query for the coordinates only:
var jsonObject = JObject.Parse(json);
var coordinates = jsonObject["results"]
.Select(x => x.SelectToken("geometry").SelectToken("location"))
.Select(x => string.Format("{0},{1}", (string)x.SelectToken("lat"), (string)x.SelectToken("lng")))
.ToArray();
This would give you an array of coordinates, eg:
[
"-33.867217,151.195939",
"-33.866786,151.195633",
...
]
Whatever approach you choose you'll be able to accomplish same results using either Newtonsoft or the .net serializer, whilst the Newtonsoft approach would allow you to query without creating strong types for deserialization.
I don't find the point of "[...] pass the valid results array from the string to be deserialized".
Maybe you need to switch to JSON.NET and do something like this:
// You simply deserialize the entire response to an ExpandoObject
// so you don't need a concrete type to deserialize the whole response...
dynamic responseEntity = JsonConvert.DeserializeObject<ExpandoObject>(
googlePlacesJson, new ExpandoObjectConverter()
);
// Now you can access result array as an `IEnumerable<dynamic>`...
IEnumerable<dynamic> results = responseEntity.results;
foreach(dynamic result in results)
{
// Do stuff for each result in the whole response...
}

Categories

Resources