Parsing Multiple Json Rows in windows phone - c#

My json response which i am generating from php :
{"name":"abhi","age":"20","id":"1"}
{"name":"abhi","age":"21","id":"4"}
And the c# code is:
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
Load(textBox1.Text);
}
public void Load(string keyword)
{
var client = new RestClient("http://localhost/query.php?name="+keyword);
var request = new RestRequest(Method.GET);
//request.AddParameter("name", keyword);
/*request.AddParameter("v", "1.0");
request.AddParameter("q", keyword);
request.AddParameter("hl", "id");
request.AddParameter("rsz", 5);*/
client.ExecuteAsync<RootObject>(request, (response) =>
{
// var resp = response.Data.ToString();
// var respLines = resp.Split('\n');
RootObject rootObject=response.Data;
listBox1.Items.Clear();
if (rootObject == null)
MessageBox.Show("null");
else
{
listBox1.Items.Add(rootObject.age+" " + rootObject.name);
}
});
}
}
}
public class RootObject
{
public string name { get; set; }
public string age { get; set; }
public string id { get; set; }
}
i am able to fetch the first row but not for multiple rows. Anyone has any idea how to fetch multiple rows in json format. How to create multiple objects of json and populate them?

That does not look like valid JSON, try returning a JSON array from PHP:
{
"rows": [
{"name":"abhi","age":"20","id":"1"},
{"name":"abhi","age":"21","id":"4"}
]
}
These would be the corresponding C# classes for deserialization:
public class Row
{
public string name { get; set; }
public string age { get; set; }
public string id { get; set; }
}
public class RootObject
{
public List<Row> rows { get; set; }
}
And you can add your rows with:
foreach (var row in rootOject.rows)
{
listBox1.Items.Add(row.age+" " + row.name);
}

Related

Unable to Deserialize data from Nested JSON List

Coming here after learning about C# classes Constructors and ArrayLists so that not to put a completely dumb question here :)
I'm trying to Deserialize below Nested Lists of JSON returned from an API GET call as below:
I've been able to get the value from the empArra (Field: Emp), but subsequent lists like yearArray, prod and sale are not returning there values.
Can you please look into the below code that where is it doing wrong?
JSON
[
{
"employee":"156718100",
"availability":[
{
"year":2018,
"sales":{
"availability":"Maybe",
"reason":""
},
"prod":{
"availability":"Maybe",
"reason":""
}
},
{
"year":2019,
"sales":{
"availability":"Maybe",
"reason":""
},
"prod":{
"availability":"Maybe",
"reason":""
}
},
{
"year":2020,
"sales":{
"availability":"Maybe",
"reason":""
},
"top":{
"availability":"Maybe",
"reason":""
}
},
{
"year":2021,
"sales":{
"availability":"Maybe",
"reason":""
},
"prod":{
"availability":"Maybe",
"reason":""
}
}
]
}
]
Classes
public class sale
{
public string SaleAvailability { get; set; }
public string SaleReason { get; set; }
public sale(string pSaleAvailability, string pSaleReason)
{
this.SaleAvailability = pSaleAvailability;
this.SaleReason = pSaleReason;
}
public override string ToString()
{
return string.Format("{0} {1}", SaleAvailability, SaleReason);
}
}
public class prod
{
public string ProdAvailability { get; set; }
public string ProdReason { get; set; }
public prod(string pProdAvailability, string pProdReason)
{
this.ProdAvailability = pProdAvailability;
this.ProdReason = pProdReason;
}
public override string ToString()
{
return string.Format("{0} {1}", ProdAvailability, ProdReason);
}
}
public class yearArray
{
public int Year { get; set; }
public yearArray(int pYear)
{
this.Year = pYear;
}
List<sale> Sale { get; set; } = new List<sale>();
List<prod> Prod { get; set; } = new List<prod>();
}
public class rootAvailability
{
public List<yearArray> YearArray { get; set; } = new List<yearArray>();
}
public class empArray
{
public string Emp { get; set; }
public List<rootAvailability> RootAvailability { get; set; } = new List<rootAvailability>();
}
public class rootArray
{
public List<empArray> EmpArrays { get; set; } = new List<empArray>();
}
main() method
(After getting the response from API)
IRestResponse response = client.Execute<rootArray>(request);
//Console.WriteLine(response.Content);
List<rootArray> rootArrays = JsonConvert.DeserializeObject<List<rootArray>>(response.Content);
List<empArray> empArrays = JsonConvert.DeserializeObject<List<empArray>>(response.Content);
List<rootAvailability> rootAvailabilities = JsonConvert.DeserializeObject<List<rootAvailability>>(response.Content);
List<yearArray> yearArrays = JsonConvert.DeserializeObject<List<yearArray>>(response.Content);
List<sale> clsSale = JsonConvert.DeserializeObject<List<sale>>(response.Content);
List<prod> clsProd = JsonConvert.DeserializeObject<List<prod>>(response.Content);
foreach (var rootitem in rootArrays)
{
foreach (var emparrayitem in empArrays)
{
Console.WriteLine("NSN: " + emparrayitem.Emp);
foreach (var rootavailabbilitiesitem in rootAvailabilities)
{
foreach (var yearArrayItem in yearArrays)
{
Console.WriteLine("Year: " + yearArrayItem.Year);
foreach (var saleItem in clsSale)
{
Console.WriteLine("SaleAvailability: " + saleItem.SaleAvailability);
Console.WriteLine("SaleReason: " + saleItem.SaleReason);
}
foreach (var prodItem in clsProd)
{
Console.WriteLine("SaleAvailability: " + prodItem.ProdAvailability);
Console.WriteLine("SaleReason: " + prodItem.ProdReason);
}
}
}
}
}
Results
Emp: 159252663
Year: 0
SaleAvailability:
SaleReason:
SaleAvailability:
SaleReason:
You have two problems with your approach:
You want to deserialize the same source over and over again (response.Content) for different class instances. It can be deserialized into one object type: your top level entity.
Your data model does not reflect your data. For example YearArray should have a single Prod and Sale property not a list of them.
You have several options how to fix it. Let me share with you the two most common ones:
With proper naming
Your object model should look like this:
public class Sale
{
public string Availability { get; set; }
public string Reason { get; set; }
}
public class Prod
{
public string Availability { get; set; }
public string Reason { get; set; }
}
public class MidLevel
{
public int Year { get; set; }
public Sale Sales { get; set; }
public Prod Top { get; set; }
}
public class TopLevel
{
public string Employee { get; set; }
public List<MidLevel> Availability { get; set; } = new List<MidLevel>();
}
Then all you need to do is to call the following command:
var result = JsonConvert.DeserializeObject<TopLevel[]>(json);
Now, your result will be populated with all the data.
With JsonProperty
If you don't want to use the same names in your domain model which is used in the json then you can define the mapping between these two worlds via JsonProperty attributes.
Now your domain model can look like this:
public class SalesInformation
{
[JsonProperty(PropertyName = "availability")]
public string Avail { get; set; }
[JsonProperty(PropertyName = "reason")]
public string Reasoning { get; set; }
}
public class ProdInformation
{
[JsonProperty(PropertyName = "availability")]
public string Availability { get; set; }
[JsonProperty(PropertyName = "reason")]
public string Reasoning { get; set; }
}
public class MidLevel
{
[JsonProperty(PropertyName = "year")]
public int AvailYear { get; set; }
[JsonProperty(PropertyName = "sales")]
public SalesInformation SalesInfos { get; set; }
[JsonProperty(PropertyName = "top")]
public ProdInformation ProdInfos { get; set; }
}
public class TopLevel
{
[JsonProperty(PropertyName = "employee")]
public string Emp { get; set; }
[JsonProperty(PropertyName = "availability")]
public List<MidLevel> Availabilities { get; set; } = new List<MidLevel>();
}
The usage would be exactly the same:
var result = JsonConvert.DeserializeObject<TopLevel[]>(json);
UPDATE: How to display data
To represent hierarchy in a console application can be achieved in may ways. Here I will use indentation. I've introduced the following tiny helper method:
public static void WriteWithIndent(int level, string message) => Console.WriteLine("".PadLeft(level * 2) + message);
With this in hand the data visualization could be achieved in the following way:
var result = JsonConvert.DeserializeObject<TopLevel[]>(json);
foreach (var topLevel in result)
{
Console.WriteLine($"Employee: {topLevel.Emp}");
foreach (var midLevel in topLevel.Availabilities)
{
WriteWithIndent(1, $"Year: {midLevel.AvailYear}");
WriteWithIndent(1, "Sales:");
WriteWithIndent(2, $"Avail: {midLevel.SalesInfos.Avail}");
WriteWithIndent(2, $"Reason: {midLevel.SalesInfos.Reasoning}");
WriteWithIndent(1, "Top:");
WriteWithIndent(2, $"Avail: {midLevel.ProdInfos.Avail}");
WriteWithIndent(2, $"Reason: {midLevel.ProdInfos.Reasoning}");
}
}
The printed output will look like this:
Employee: 156718100
Year: 2018
Sales:
Avail: Maybe
Reason:
Top:
Avail: Maybe
Reason:
Year: 2019
Sales:
Avail: Maybe
Reason:
Top:
Avail: Maybe
Reason:
Year: 2020
Sales:
Avail: Maybe
Reason:
Top:
Avail: Maybe
Reason:
Year: 2021
Sales:
Avail: Maybe
Reason:
Top:
Avail: Maybe
Reason:

Trying to create a new item in list in c#

I'm having a hard time to bind one particular field called url in a List.
This is my json format:
{
id: 'someID',
name: 'someName.pdf',
url: {
download: 'https://mydomain/api_binary/v1/document/mcipv7sgq11c9e6e42upqapc7k '
}
}
This is my model
public class CantoItem
{
public string id { get; set; }
public string name { get; set; }
[JsonProperty("default")]
public DefaultNest Default { get; set; }
[JsonProperty("url")]
public ResultUrl Url { get; set; }
[JsonProperty("tag")]
public object Tag { get; set; }
}
public partial class ResultUrl
{
[JsonProperty("preview")]
public Uri Preview { get; set; }
[JsonProperty("download")]
public Uri Download { get; set; }
}
[JsonProperty("tag")]
public List<string> Tag { get; set; }
}
Then for adding the value I have:
var cantoAssetMetadata = new List<CantoItem>();
foreach (JValue item in collection)
{
try
{
var collectionjObj = JObject.Parse(item.ToString());
cantoAssetMetadata.Add(new CantoItem()
{
id = collectionjObj["id"].ToString(),
name = collectionjObj["name"].ToString(),
Url = collectionjObj["url"].ToString(),
Tag = collectionjObj["tag"].ToString(),
});
}
catch (Exception ex)
{
Console.WriteLine($"Exeption: {ex}, {item}");
}
}
Other fields are set correctly just the URL is not, I canĀ“t figure out how I can set the value correctly. Any help will be appreciated
The following wouldn't work:
Url = collectionjObj["url"].ToString()
You will need to initialize the Url and set the related property:
name = collectionjObj["name"].ToString(),
Url = new ResultUrl()
{
Download = new System.Uri(collectionjObj["url"].ToString())
},
Tag = collectionjObj["tag"].ToString(),
Why not try
var cantoAssetMetadata = new List<CantoItem>();
foreach (JValue item in collection)
{
try
{
cantoAssetMetadata.Add(item.ToObject<CantoItem>());
}
catch (Exception ex)
{
Console.WriteLine($"Exeption: {ex}, {item}");
}
}
You are calling .ToString() on a class object - Url = collectionjObj["url"].ToString(), Url is a partial class called ResultUrl. Convert the JToken to the appropriate class which it deserializes to
//Convert to the proper class object type
Url = collectionjObj["url"].ToObject<ResultUrl>;

How to get JSON result into List

I have my own code here and already get the JSON result then I haven't idea to move the JSON result into the interface (IEntities function) list below.
class GetCategory : IEntities
{
private JsonHandle _jsonhandle;
private string _ocategory;
public async void TaskCategory()
{
_jsonhandle = new JsonHandle();
_jsonhandle.StrAPI = "http://api.nytimes.com/svc/books/v3/lists/names.json?api-key=7bb034b7693d6f9753b2f68e00b98c78%3A16%3A73599437";
var client = new HttpClient();
Task<string> datatask = client.GetStringAsync(_jsonhandle.StrAPI);
try
{
var JsonRead = await datatask;
JObject oCategory = JObject.Parse(JsonRead);
List<JToken> results = oCategory["results"].Children().ToList();
//serialize JSON results into .NET objects
List<object> dtCategory = new List<object>();
foreach (JToken result in results)
{
object _dtcategory = JsonConvert.DeserializeObject<object>(result.ToString());
dtCategory.Add(_dtcategory);
var listname = result["list_name"];
}
}
catch (Exception error)
{
Console.WriteLine("AW!" + error.StackTrace);
}
public List<object> BookCategory()
{
}
}
In the last function that in IEntities interface, I need to put my JSON result in interface List<object>.
When working with JSON, the first thing to do is creating a model object. In order to this, either you should analyze JSON output manually, or you can generate the model automatically by going to the following link and pasting either the JSON your are going to use or the service link;
json2csharp.com
I've just used your API link and the output generated is;
public class Result
{
public string list_name { get; set; }
public string display_name { get; set; }
public string list_name_encoded { get; set; }
public string oldest_published_date { get; set; }
public string newest_published_date { get; set; }
public string updated { get; set; }
}
public class RootObject
{
public string status { get; set; }
public string copyright { get; set; }
public int num_results { get; set; }
public List<Result> results { get; set; }
}
This will be our model.
Secondly, as far as I can see, what you want to do is only to get the result list, thus, as you deserialize the JSON output, you are going to use the Model.Result and move them into a list.
Then, to get the response, a private method can be used which that returns an async Task<string>, and on the BookCategory() method, you can get the Results and deserialize JSON and initialize a list based on your JSON object model;
public List<Model.Result> BookCategory()
{
List<Model.Result> list = new List<Model.Result>();
var model = JsonConvert.DeserializeObject<Model.RootObject>(TaskCategory().Result);
list = model.results;
return list;
}
Deserializing JSON is as simply as below;
var model = JsonConvert.DeserializeObject<Model.RootObject>(TaskCategory().Result);
Model.cs
using System.Collections.Generic;
namespace SO1
{
public class Model
{
public class Result
{
public string list_name { get; set; }
public string display_name { get; set; }
public string list_name_encoded { get; set; }
public string oldest_published_date { get; set; }
public string newest_published_date { get; set; }
public string updated { get; set; }
}
public class RootObject
{
public string status { get; set; }
public string copyright { get; set; }
public int num_results { get; set; }
public List<Result> results { get; set; }
}
}
}
GetCategory.cs
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Net.Http;
using System;
namespace SO1
{
public class GetCategory : IEntities
{
private String BaseUri;
public GetCategory(string BaseUri)
{
this.BaseUri = BaseUri;
}
private async Task<string> TaskCategory()
{
var httpClient = new HttpClient();
var parameters = new Dictionary<string, string>();
parameters["text"] = "text";
var response = await httpClient.GetStringAsync(BaseUri);
return response;
}
public List<Model.Result> BookCategory()
{
List<Model.Result> list = new List<Model.Result>();
var model = JsonConvert.DeserializeObject<Model.RootObject>(TaskCategory().Result);
list = model.results;
return list;
}
}
}
IEntities
using System.Collections.Generic;
namespace SO1
{
public interface IEntities
{
List<Model.Result> BookCategory();
}
}
Program.cs
using System;
using System.Collections.Generic;
namespace SO1
{
class Program
{
static void Main(string[] args)
{
string BaseUri = "http://api.nytimes.com/svc/books/v3/lists/names.json?api-key=7bb034b7693d6f9753b2f68e00b98c78%3A16%3A73599437";
IEntities entity = new GetCategory(BaseUri);
List<Model.Result> listBookCategory = new List<Model.Result>();
listBookCategory = entity.BookCategory();
foreach (Model.Result r in listBookCategory)
{
Console.WriteLine();
Console.WriteLine("...List Name : " + r.list_name);
Console.WriteLine("...Display Name : " + r.display_name);
Console.WriteLine("...List Name Encoded : " + r.list_name_encoded);
Console.WriteLine("...Oldest Published Date : " + r.oldest_published_date);
Console.WriteLine("...Oldest Published Date : " + r.newest_published_date);
Console.WriteLine("...Updated : " + r.updated);
Console.WriteLine();
}
}
}
}
Output (only first three results printed)
...List Name : Combined Print and E-Book Fiction
...Display Name : Combined Print & E-Book Fiction
...List Name Encoded : combined-print-and-e-book-fiction
...Oldest Published Date : 2011-02-13
...Oldest Published Date : 2015-12-27
...Updated : WEEKLY
...List Name : Combined Print and E-Book Nonfiction
...Display Name : Combined Print & E-Book Nonfiction
...List Name Encoded : combined-print-and-e-book-nonfiction
...Oldest Published Date : 2011-02-13
...Oldest Published Date : 2015-12-27
...Updated : WEEKLY
...List Name : Hardcover Fiction
...Display Name : Hardcover Fiction
...List Name Encoded : hardcover-fiction
...Oldest Published Date : 2008-06-08
...Oldest Published Date : 2015-12-27
...Updated : WEEKLY

How to extract the data from Generic <T> List object

I wanna create the generic function inwhich I will just pass the class name and get the data in CSV format that is from JSON object on the bases of Generic Class Type.
But I am not able to access the class member while foreach loop.
public class Lifetouch
{
public int LifetouchID { get; set; }
public string Data { get; set; }
}
public class Lifetemp
{
public int LifetempID { get; set; }
public string Data { get; set; }
}
main()
{
getPerodicListofVitalSigns <Lifetouch>(new Lifetouch());
}
public static void getPerodicListofVitalSigns <T>( T clazz)
{
List<T> list_of_measurements_Original = JsonConvert.DeserializeObject<List<T>>(json_response);
// Got the list_of_measurements_Original count 2.
StringBuilder sb = new StringBuilder();
sb.Append("[");
foreach (var element in list_of_measurements_Original)
{
sb.Append(element.LifetouchID + ", ") // Not able to access the element of list LifetouchID
}
sb.Append("]");
}
I would like to create the generic function inwhich I will just pass the class name and get the data (ID's) in CSV format that is from JSON object on the bases of Generic Class Type. That all the ids will pass through webservice and update the database. Its the requirement.
I would like to create the Generic function in which I would like to pass the class name as a paramenter. So in future its easy for me to use that generic function if new class added.
Now its working fine..
public class Lifetouch
{
public int LifetouchID { get; set; }
public string Data { get; set; }
}
public class Lifetemp
{
public int LifetempID { get; set; }
public string Data { get; set; }
}
main()
{
getPerodicListofVitalSigns <Lifetouch>(new Lifetouch());
getPerodicListofVitalSigns <Lifetemp>(new Lifetemp());
}
public static void getPerodicListofVitalSigns <T>( T clazz)
{
List<T> list_of_measurements_Original = JsonConvert.DeserializeObject<List<T>>(json_response);
// Got the list_of_measurements_Original count 2.
StringBuilder sb = new StringBuilder();
sb.Append("[");
foreach (var element in list_of_measurements_Original)
{
if (VitalSignName == "Lifetouch")
{
var vitalSign = element as Lifetouch;
dataString = dataString + (vitalSign.LifetouchID + ",");
}
else if (VitalSignName == "Lifetemp")
{
var vitalSign = element as Lifetemp;
dataString = dataString + (vitalSign.LifetempID + ",");
}
}
sb.Append("]");
string WebserviceAddress = "192..../json/reply/UpdateSyncStatus";
JSON_POST_Sender.ClassPost(WebserviceAddress, dataString), "true")
}

How to parse the Json data in windows phone 8

I am new to windows phone 8 development. I am working on application in which I need parse the Json. so I am not able to get the following data in windows phone 8.
{
"response":{
"errorFlag":0,
"Score Detail":{
"39":[
{
"test_date":"2013-06-28",
"total_marks":"50",
"score":"14"
},
{
"test_date":"2013-08-08",
"total_marks":"20",
"score":"20"
}
],
"40":[
{
"test_date":"2013-08-08",
"total_marks":"20",
"score":"20"
},
{
"test_date":"2013-08-08",
"total_marks":"30",
"score":"20"
},
{
"test_date":"2013-08-08",
"total_marks":"30",
"score":"20"
}
],
"50":[
{
"test_date":"2013-08-08",
"total_marks":"30",
"score":"20"
}
]
}
}
}
I am trying to parse the data in the following way
namespace testscore
{
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
Loaded += new RoutedEventHandler(Mainpage_Loaded);
}
void Mainpage_Loaded(object sender, RoutedEventArgs e)
{
WebClient webClient1 = new WebClient();
webClient1.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient1_DownloadStringCompleted);
webClient1.DownloadStringAsync(new Uri("some link"));
}
public void webClient1_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var rootObject = JsonConvert.DeserializeObject<RootObject>(e.Result);
MessageBox.Show(e.Result.ToString());
foreach (var res in rootObject.response.ScoreDetail)
{
string rs = res.Key;
MessageBox.Show(rs.ToString());
......
}
}
public class RootObject
{
public Response response { get; set; }
}
public class Response
{
public int errorFlag { get; set; }
[JsonProperty("Score Detail")]
public JObject ScoreDetail { get; set; }
}
Here I am to getting key value (here it is 39) but I am not able to get the values of the score, testdate and marks. please help me in parsing these details.
Thanks in advance.
I propose you to build classes of your json :
public class RootObject
{
public Response response { get; set; }
}
public class Response
{
public int errorFlag { get; set; }
[JsonProperty("Score Detail")]
public JObject ScoreDetail { get; set; }
}
You can use them on the DownloadStringCompleted event :
public void webClient1_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
RootObject root = JsonConvert.DeserializeObject<RootObject>(e.Result);
JObject obj = root.response.ScoreDetail;
foreach (KeyValuePair<string, JToken> pair in obj)
{
string key = pair.Key; // here you got 39.
foreach (JObject detail in pair.Value as JArray)
{
string date = detail["test_date"].ToString();
string score = detail["score"].ToString();
string total_marks = detail["total_marks"].ToString();
}
}
}
Hope it helps !
var result= JObject.Parse(response)["response"]["ScoreDetail"];
foreach (var item in result)
{
// Code to store the result
}

Categories

Resources