Can't get data from deserialized Json string - c#

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)));

Related

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);
}

Task and deserializing objects from api logic and deserializing json

I was hoping someone could help walk me through some of this logic here. I hope this isn't too specific so that maybe it will help other people. It will definitely seem that way, I am sure, but I don't know if this is is common in industry or not (I am supposed to be an economist, but I am helping with the programming until we get someone more skilled at this trade).
The background: I was asked to deserialize a json object that is returned by the api, but I am not sure if I am understanding the code correctly so until then I won't be able to deserialize it. My two hopes are that someone can correct me if my logic is incorrect and to help me figure out how to deserialize it.
The goal is pretty simple: show a list using a UITableView of the items that are returned from the api. I have the UITableView that is all set up. I just need to fill it with the data now. Here is what was written before me. It is the task/api:
public async Task<Food> FoodCatalog(int category)
{
string url = Service.baseURL + Service.FoodCatalog + "?category=" + category.ToString();
dynamic results = await Service.getDataFromService(url).ConfigureAwait(false);
string json = results as string; // Otherwise error next line ???
Food items = JsonConvert.DeserializeObject<Food>(json);
return items;
}
Here is the Food class:
public struct FoodStruct
{
[JsonProperty(PropertyName = "FoodGroupTypeId")] public short? FoodGroupTypeId;
[JsonProperty(PropertyName = "FoodGroupDescription")] public string FoodGroupDescription;
[JsonProperty(PropertyName = "FoodId")] public int? FoodId;
[JsonProperty(PropertyName = "FoodDescription")] public string FoodDescription;
}
public class Food
{
[JsonProperty(PropertyName = "Table Selection")] public static List<FoodStruct> FoodList = new List<FoodStruct>();
public FoodStruct this[int key] { get { return FoodList[key]; } }
public static string[] ToStringArray()
{
string[] list = new string[FoodList.Count];
int i = 0;
foreach (FoodStruct fs in FoodList)
{
list[i++] = fs.FoodDescription;
}
return list;
}
public static implicit operator string(Food v)
{
throw new NotImplementedException();
}
}
The api has a task that connects to the url, gets the results, and returns the deserialized object as a class? Is that how this logic works?
The Food class looks like it does what I want it to. It looks like it creates a list of the food description (the food group, etc isn't terribly important yet). But I have no way of accessing that food list and I am really not completely sure this is doing what I want it to, but it seems that way.
Can someone correct me on the logic and help me figure out how to deserialize the object to put it in the UITableView?
Deserialize you response like below
public async Task<Food> FoodCatalog(int category)
{
string url = Service.baseURL + Service.FoodCatalog + "?category=" + category.ToString();
dynamic results = await Service.getDataFromService(url).ConfigureAwait(false);
string json = results as string; // Otherwise error next line ???
var items = JsonConvert.DeserializeObject<List<Food>>(json);
return items;
}
In your ViewController bind your UITableView
public async override void ViewDidLoad()
{
//Create your API class object & call foodCatalog method here
var items=await FoodCatalog(params)
//Bind your UITableView
mainListview.Source = new TableViewSource(items);
}
For more information about how to bind TableView visit this
You can use Newtonsoft.Json:
string foodJson = "[{\"FoodGroupTypeId\":\"apple\", \"FoodGroupDescription\":\"apple fruit\",\"FoodId\": \"Fuji Apple\",\"FoodDescription\": \"Fuji Apple\"}]";
var obj = (Newtonsoft.Json.Linq.JArray)JsonConvert.DeserializeObject(foodJson);
foreach (var ch in obj.Children())
{
string id = ch["FoodGroupTypeId"].ToString();
}

Parsing JSON list to int array in 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);
}

Create json in UWP without JSON.Net

I am trying to create a json formatted string using c# in UWP without JSON.Net, but I am just not understanding how to get there. Let's say I wanted to create the following json dynamically:
[{"id":130},{"id":131},{"id":132},{"id":133},{"id":134}]
From everything I have read, it would seem that I need a class that defines the content of my json. For example:
class accountTypes
{
public int id { get; set; }
public string type { get; set; }
}
From there, it would seem that I only need to create a list of type "accountTypes" and then add each "id" to the list.
List<accountTypes> jsonList = new List<accountTypes>();
int numOfChildren = AccountTypesList.Children.Count;
for (int i = 0; i < numOfChildren; i++)
{
if (((CheckBox)AccountTypesList.Children[i]).IsChecked == true)
{
jsonList.Add(new accountTypes() { id = (int)(double)((CheckBox)AccountTypesList.Children[i]).Tag });
}
}
While I am 99% sure that the above code is very flawed, it does not crash on me, so that is a start at least. What I am struggling with now though is how I would serialize the list "jsonList". Everything I have read thus far either points to JSON.net or the JavaScriptSerializer Class, and not Windows.Data.Json. If I could see a simple example on how to serialize json using Windows.Data.Json, then I could at least visualize what is going on with my list and could correct it accordingly. That being said, how do I serialize an array or a list using Windows.Data.Json?
First of all, there's no built-in JSON-serializer that handles all the mapping for you. This is exactly what JSON.NET is doing for you. Therefore, you have to take the manual and long way.
To create exactly this result:
[{"id":130},{"id":131},{"id":132},{"id":133},{"id":134}]
You have to use the JsonArray class. For example, pass your jsonList object to a method like this:
public string ToJson(List<accountTypes> objectList)
{
var jArray = new JsonArray();
foreach (var at in objectList)
{
jArray.Add(ToJson(at));
}
return jArray.ToString();
}
Whereas you use this method to create a JsonObject for your class object itself (as manual step as well):
public JsonObject ToJson(accountTypes at)
{
var jObj = new JsonObject();
jObj.SetNamedValue("id", JsonValue.CreateNumberValue(at.id));
return jObj;
}

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