How to query data from json in c# windows phone - c#

I am new to windows phone dev. I'm working on an app that fetch json from a web service and parse it and display it to the app. I used json.net to parse it. here's my json file:
[
{
"id": "001",
"title": "title1",
"content": "sample content",
"category_id": "3",
"image": "defaultimg.jpg"
},
{
"id": "021",
"title": "title2",
"content": "sample content",
"category_id": "1",
"image": "defaultimg2.jpg"
},
{
"id": "011",
"title": "title3",
"content": "sample content",
"category_id": "3",
"image": "defaultimg22.jpg"
},
{
"id": "008",
"title": "title24",
"content": "sample content",
"category_id": "2",
"image": "defaultimg12.jpg"
},
{
"id": "121",
"title": "title12",
"content": "sample content",
"category_id": "3",
"image": "defaultimg27.jpg"
}
]
so I came up with this class with the help of json2csharp.com
public class RootObject
{
public string id { get; set; }
public string title { get; set; }
public string content { get; set; }
public string category_id { get; set; }
public string image { get; set; }
}
here's my code in cs
var data = new WebClient();
Observable
.FromEvent<DownloadStringCompletedEventArgs>(data, "DownloadStringCompleted")
.Subscribe(r =>
{
var deserialized =
JsonConvert.DeserializeObject<List<RootObject>>(r.EventArgs.Result);
ListBox1.ItemsSource = deserialized;
});
data.DownloadStringAsync(
new Uri("http://sampleurl.com/xyz/myjson.aspx"));
I want to display only those who has "category_id": "9" on the listbox1
can you help me how to filter this data? im a student and new in c# windows phone. Thanks!

You would generally want to use LINQ to manipulate your List<RootObject>, something like:
var deserialized = JsonConvert.DeserializeObject<List<RootObject>>(r.EventArgs.Result);
// select only RootObjects with category_id equal to 9
ListBox1.ItemsSource = deserialized.Where(r => r.category_id == 9);

If the API itself does not have an endpoint that allows you to query for only those records with category_id : 9 then you'll have to do the filtering at the client to populate your listbox. One common and easy way to do that is with LINQ.
Here is an example of what the LINQ syntax would look like:
var categoryNineOnly = data.Where(x=>x.category_id == 9)
Much more detail here:
http://msdn.microsoft.com/en-us/library/vstudio/bb397926.aspx

Related

How to group JSON data by ID in C#

Getting JSON in this format after serializing the data from the data table
This is the result after reading the excel file and storing the data in a data table. Later serialized using newtosoft.json into below JSON output
JSON getting now below:
[{ "Id": "1", "Profit": "33.332999999999998", "Telephone": "123", "Email": "user1#testmail.com" }, { "Id": "1", "Profit": "21.21", "Telephone": "43", "Email": "user11#testmail.com" }, { "Id": "2", "Profit": "49.000999999999998", "Telephone": "22", "Email": "user2#testmail.com" }, { "Id": "2", "Profit": "10.1", "Telephone": "876", "Email": "user22#testmail.com" }]
Expected format
[{ "Id": "1", "Profits": ["33.332999999999998", "21.21"], "Telephones": ["43", "123"], "Emails": ["user1#testmail.com", "user11#testmail.com"] }, { "Id": "2", "Profits": ["49.000999999999998", "10.1"], "Telephones": ["876", "22"], "Emails": ["user2#testmail.com", "user22#testmail.com"] }]
Can anyone please help with this?
try this
var json=...origin json
var jD = JsonConvert.DeserializeObject<DataOrigin[]>(json);
jD=jD.OrderBy(d => d.Id).ToArray();
var prevId=string.Empty;
var list=new List<Data>();
foreach (var item in jD)
{
if(item.Id!=prevId)
{
prevId=item.Id;
list.Add(new Data(Convert.ToInt32(item.Id), item.Profit, item.Telephone, item.Email));
}
else
{
var prevIdInt=Convert.ToInt32(prevId);
var prevItem=list.Last(l =>l.Id==prevIdInt );
prevItem.MergeItem(item.Profit,item.Telephone,item.Email);
}
}
var result = JsonConvert.SerializeObject(list);
result
[
{
"Id": 1,
"Profits": [
33.333,
21.21
],
"Telephones": [
"123",
"43"
],
"Emails": [
"user1#testmail.com",
"user11#testmail.com"
]
},
{
"Id": 2,
"Profits": [
49.001,
10.1
],
"Telephones": [
"22",
"876"
],
"Emails": [
"user2#testmail.com",
"user22#testmail.com"
]
}
]
classes
public class DataOrigin
{
public string Id { get; set; }
public double Profit { get; set; }
public string Telephone { get; set; }
public string Email { get; set; }
}
public class Data
{
public int Id { get; set; }
public List<double> Profits { get; set; }
public List<string> Telephones { get; set; }
public List<string> Emails { get; set; }
public Data(int id,double profit,string phone, string email)
{
Id=id;
Profits = new List<double>(){profit};
Telephones = new List<string>(){phone};
Emails = new List<string>(){email};
}
public void MergeItem (double profit,string phone, string email)
{
Profits.Add(profit);
Telephones.Add(phone);
Emails.Add(email);
}
}
Here is the solution:
var data = [{
"Id": "1",
"Profit": "33.332999999999998",
"Telephone": "123",
"Email": "user1#testmail.com"
}, {
"Id": "1",
"Profit": "21.21",
"Telephone": "43",
"Email": "user11#testmail.com"
}, {
"Id": "2",
"Profit": "49.000999999999998",
"Telephone": "22",
"Email": "user2#testmail.com"
}, {
"Id": "2",
"Profit": "10.1",
"Telephone": "876",
"Email": "user22#testmail.com"
}]
var temp = {};
data.forEach(x => {
if (temp[x.Id] == undefined) {
temp[x.Id] = {}
temp[x.Id]['Id'] = x.Id
temp[x.Id]['Profit'] = []
temp[x.Id]['Telephone'] = []
temp[x.Id]['Email'] = []
}
temp[x.Id].Profit.push(x.Profit)
temp[x.Id].Telephone.push(x.Telephone)
temp[x.Id].Email.push(x.Email)
})
var finalResponse = []
for (const [key, value] of Object.entries(temp)) {
finalResponse.push(value)
}

Deserialize JSON with Newtonsoft

I'm having problems with this JSON to use it in combobox and datagridview. I'm using Newtonsoft to do it:
{
"users": [
{
"id": 1,
"name": "Test 1",
"email": "test1#test.com",
"events": [
{
"id": 1,
"name": "Event 1",
"date": "11/10/2019",
"finish": 0
},
{
"id": 2,
"name": "Event 2",
"date": "12/10/2019",
"finish": 0
}
]
},
{
"id": 2,
"name": "Test 2",
"email": "test2#test.com",
"events": [
{
"id": 2,
"name": "Event 2",
"date": "17/10/2019",
"finish": 0
}
]
}
]
}
And this is the class (JsonEvent.cs). Generated with json2csharp.com:
using System;
using System.Collections.Generic;
namespace TestDO.Models
{
class JsonEvent
{
public partial class Admin
{
public List<User> Users { get; set; }
}
public partial class User
{
public long Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public List<Event> Events { get; set; }
}
public partial class Event
{
public long Id { get; set; }
public string Name { get; set; }
public string Date { get; set; }
public long Finish { get; set; }
}
}
}
But now, I do not know how to use the result with combobox datasource or a datagrid.
So far the only time I've worked with this has been for a much simpler topic like this (this is and example, It is not related to this):
JsonResponde.cs
namespace TestDO.Models
{
class JsonResponse
{
public string Upgraded { get; set; }
public string time{ get; set; }
}
}
And then I check the result of Upgraded like this:
var jResponse = JsonConvert.DeserializeObject<JsonResponse>(json);
if (jResponse.Upgraded == "true")
But I don't know how to do it with a more complex json.
I want to use event id for combobox and event name for display.
And for datagrid, user id, user name, event name, event date for each line.
Thank you in advance for any help to solve the problem.
Your C# representation of the JSON you provided seems to perfectly fine and matching. Therefor you should be able to do something like the following:
var jResponse = JsonConvert.DeserializeObject<Admin>(json);
If the JSON array Users is not nested in another object you could also convert it to a List<User> (HashSet or similar collections should also work), if it's the only property of your Admin class. This would look something like this:
var jResponse = JsonConvert.DeserializeObject<List<User>>(json);
For this to work your JSON would need to look something like this:
[
{
"id": 1,
"name": "Test 1",
"email": "test1#test.com",
"events": [
{
"id": 1,
"name": "Event 1",
"date": "11/10/2019",
"finish": 0
},
{
"id": 2,
"name": "Event 2",
"date": "12/10/2019",
"finish": 0
}
]
},
{
"id": 2,
"name": "Test 2",
"email": "test2#test.com",
"events": [
{
"id": 2,
"name": "Event 2",
"date": "17/10/2019",
"finish": 0
}
]
}
]
Edit
If you want to feed your users to a combo-box, you can just pass the list to the combo-box. See the example below:
ComboBox cb = new ComboBox();
cb.DataSource = jResponse.Users.SelectMany(x => x.Events.OrderBy(y => y.Id).Select(y => y.Name));
Of course your Users object contains a lot of information, that is just an assumption, that you want to have all the names of the users in the ComboBox.
You need to deserialize your json to an object of the Admin class you created, which you can do like this:
var AdminObj = JsonConvert.DeserializeObject<Admin>(json);
From there, you have access your Users list by AdminObj.Users, which you can loop through to get whatever data you need for your application.

Need help deserializing JSON Object returned from API

I have the following JSON Output:
{{
"$type": "Asi.Soa.Core.DataContracts.PagedResult`1[[Asi.Soa.Core.DataContracts.GenericEntityData, Asi.Contracts]], Asi.Contracts",
"Items": {
"$type": "System.Collections.Generic.List`1[[Asi.Soa.Core.DataContracts.GenericEntityData, Asi.Contracts]], mscorlib",
"$values": [
{
"$type": "Asi.Soa.Core.DataContracts.GenericEntityData, Asi.Contracts",
"EntityTypeName": "14",
"Properties": {
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyDataCollection, Asi.Contracts",
"$values": [
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "ResultRow",
"Value": "1"
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "Work Phone",
"Value": "(782) 438-7600"
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "Email",
"Value": "agsaz#rmax.net"
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "Full Name",
"Value": "Agazny"
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "iMISId",
"Value": "eg1"
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "Preferred Phone",
"Value": "780"
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "Organization",
"Value": "Re"
}
]
}
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericEntityData, Asi.Contracts",
"EntityTypeName": "14",
"Properties": {
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyDataCollection, Asi.Contracts",
"$values": [
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "ResultRow",
"Value": "2"
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "Work Phone",
"Value": "7802"
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "Email",
"Value": "aksm"
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "Full Name",
"Value": "Aji"
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "iMISId",
"Value": "esa"
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "Preferred Phone",
"Value": "780"
},
{
"$type": "Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts",
"Name": "Organization",
"Value": "Hom"
}
]
}
}
I am trying to deserialize this response into workable c# objects and POST it to a different API that accepts a totally different format of JSON.
This is my code so far:
using (var client = new HttpClient())
{
// Format headers
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Request token, and append to headers
await AddTokenToHeaders(client);
// Query HTTP Service
var response = await client.GetAsync(baseUrl + "api/IQA?querydocumentversionkey=f2005a6e-7f47-47c3-a7e7-bbd2a7b6ab38");
if (response.IsSuccessStatusCode)
{
var customer = await response.Content.ReadAsStringAsync();
JObject result = JObject.Parse(await response.Content.ReadAsStringAsync());
JArray a = (JArray)result["Items"]["$values"][0]["Properties"];
var test = a.AsJEnumerable();
However, it's not picking up my entire JSON object and I am not able to map it to the properties of my class:
--Update.
I have updated my code and I was able to get the Jarray in the format I wanted, however when I try enumerate by jObject into my List of Class Customer, the properties I try to cast returns nulls.
Thanks for the response. I was able to get the output I was looking for by using the following code. However, attempting to put the output in my List of Customer class with the properties specified however, I am getting nulls on the properties of class Customer.
JObject result = JObject.Parse(await response.Content.ReadAsStringAsync());
JArray a = (JArray)result["Items"]["$values"];
List<Customer> items = ((JArray)a).Select(x => new Customer
{
ResultRow = (string)x["ResultRow"],
WorkPhone = (string)x["Work Phone"],
Email = (string)x["Email"],
FullName = (string)x["Full Name"],
iMISId = (string)x["iMISId"],
PreferredPhone = (string)x["Preferred Phone"],
Organization = (string)x["Organization"]
}).ToList();
public class Customer
{
[JsonProperty("ResultRow")]
public string ResultRow { get; set; }
[JsonProperty("Work Phone")]
public string WorkPhone { get; set; }
[JsonProperty("Email")]
public string Email { get; set; }
[JsonProperty("Full Name")]
public string FullName { get; set; }
[JsonProperty("iMISId")]
public string iMISId { get; set; }
[JsonProperty("Preferred Phone")]
public string PreferredPhone { get; set; }
[JsonProperty("Organization")]
public string Organization { get; set; }
}
There is a mistake in the code you provided. You are trying to cast the Properties into a JArray when it is an object.
If you do want the array in the Properties object, do this:
JArray arr = (JArray)result["Items"]["$values"][0]["Properties"]["$values"];
Otherwise, if you are looking for the Properties object, then you should do this instead:
JObject obj = (JObject)result["Items"]["$values"][0]["Properties"];
Finally, to rebuild the list of Customer instances, you could use the following logic with the static methods:
var customersJson = (JArray)result["Items"]["$values"];
var customers = new List<Customer>();
foreach (JObject o in customersJson)
{
var customerJson = (JArray) o["Properties"]["$values"];
customers.Add(BuildCustomer(customerJson));
}
[...]
private static Customer BuildCustomer(JArray a)
{
return new Customer
{
ResultRow = GetValue(a, "ResultRow"),
WorkPhone = GetValue(a, "Work Phone"),
Email = GetValue(a, "Email"),
FullName = GetValue(a, "Full Name"),
iMISId = GetValue(a, "iMISId"),
PreferredPhone = GetValue(a, "Preferred Phone"),
Organization = GetValue(a, "Organization")
};
}
private static string GetValue(JArray array, string name)
{
JToken obj = array.FirstOrDefault(x => (string) x["Name"] == name);
if (obj == null)
return string.Empty;
return (string) obj["Value"];
}

Google Play Developer Api and JsonConvert.DeserializeObject

I am trying to deserialize an AchievementConfigurations: list REST Response from here https://developers.google.com/games/services/publishing/api/achievementConfigurations/list.
The problem is that this line only fills out the top level object and the List remains empty. No error messages are throw which makes this difficult to track down what is going on. I used a website to generate the json structured classes and after that I removed the duplicates which where unnecessary.
The response looks like this, I have removed the achievementConfiguration resource because it is really long but it can be found here https://developers.google.com/games/services/publishing/api/achievementConfigurations#resource
{
"kind": "gamesConfiguration#achievementConfigurationListResponse",
"nextPageToken": string,
"items": [
achievementConfigurations Resource
]
}
I have a series of classes I have created mirroring the data starting with the AchievementConfigurationListResponse class
public class AchievementConfigurationListResponse
{
public string kind = "gamesConfiguration#achievementConfigurationListResponse";
public string nextPageToken = "";
List<AchievementConfigurationResource> items = new List<AchievementConfigurationResource>();
}
Next up is the AchievementConfigurationResource which is an item in the list, it has several nested objects
public class AchievementConfigurationResource
{
public static string[] types = new string[] { "STANDARD", "INCREMENTAL" };
public static string[] states = new string[] { "REVEALED", "HIDDEN", "UNLOCKED" };
public string kind = "gamesConfiguration#achievementConfiguration";
public string token = "";
public string id = "";
public string achievementType = types[0];
public string initialState = states[0];
public int? stepsToUnlock;
public AchievementConfigurationDetail draft = new AchievementDataResource();
public AchievementConfigurationDetail published = new AchievementDataResource();
}
Those nested object are of this type of AchievementConfigurationDetail
public class AchievementConfigurationDetail
{
public string kind = "gamesConfiguration#achievementConfigurationDetail";
public LocalizedStringBundle name = new LocalizedStringBundle();
public LocalizedStringBundle description = new LocalizedStringBundle();
public int pointValue = 5;
public string iconUrl = "";
public int sortRank = 1;
}
Which contains several LocalizedStringBundles
public class LocalizedStringBundle
{
public string kind = "gamesConfiguration#localizedStringBundle";
public List<Translation> translations = new List<Translation>();
public class Translation
{
public string kind = "gamesConfiguration#localizedString";
public string locale = "en-US";
public string value = "";
}
}
I call this on the json with the following line:
AchievementConfigurationListResponse res = JsonConvert.DeserializeObject<AchievementConfigurationListResponse>(content);
Here is a copy of the response, sensitive data removed but the keys and structure are all intact. This one only contains a single record because the full file is something like 5000 lines long.
{
"kind": "gamesConfiguration#achievementConfigurationListResponse",
"items": [
{
"kind": "gamesConfiguration#achievementConfiguration",
"token": "Unique Token",
"id": "Unique ID",
"achievementType": "STANDARD",
"initialState": "REVEALED",
"draft": {
"kind": "gamesConfiguration#achievementConfigurationDetail",
"name": {
"kind": "gamesConfiguration#localizedStringBundle",
"translations": [
{
"kind": "gamesConfiguration#localizedString",
"locale": "en-US",
"value": "Name"
}
]
},
"description": {
"kind": "gamesConfiguration#localizedStringBundle",
"translations": [
{
"kind": "gamesConfiguration#localizedString",
"locale": "en-US",
"value": "Description"
}
]
},
"pointValue": 5,
"iconUrl": "Icon url",
"sortRank": 1
},
"published": {
"kind": "gamesConfiguration#achievementConfigurationDetail",
"name": {
"kind": "gamesConfiguration#localizedStringBundle",
"translations": [
{
"kind": "gamesConfiguration#localizedString",
"locale": "en-US",
"value": "Name"
}
]
},
"description": {
"kind": "gamesConfiguration#localizedStringBundle",
"translations": [
{
"kind": "gamesConfiguration#localizedString",
"locale": "en-US",
"value": "Description"
}
]
},
"pointValue": 5,
"iconUrl": "Icon url",
"sortRank": 1
}
}
]
}
Json.NET does not serialize private members by default. Thus you need to make AchievementConfigurationListResponse.items be public:
public List<AchievementConfigurationResource> items = new List<AchievementConfigurationResource>();
Alternatively, mark it with [JsonProperty] which enables serialization of private members:
[JsonProperty]
List<AchievementConfigurationResource> items = new List<AchievementConfigurationResource>();

Deserialize JSON subdocument

I'm calling the JIRA Rest API to recieve a list of Worklog Objects.
The JSON I recieve looks like.
{
"startAt": 0,
"maxResults": 1,
"total": 1,
"worklogs": [
{
"self": "http://www.example.com/jira/rest/api/2/issue/10010/worklog/10000",
"author": {
"self": "http://www.example.com/jira/rest/api/2/user?username=fred",
"name": "fred",
"displayName": "Fred F. User",
"active": false
},
"updateAuthor": {
"self": "http://www.example.com/jira/rest/api/2/user?username=fred",
"name": "fred",
"displayName": "Fred F. User",
"active": false
},
"comment": "I did some work here.",
"visibility": {
"type": "group",
"value": "jira-developers"
},
"started": "2015-08-25T07:43:10.086+0000",
"timeSpent": "3h 20m",
"timeSpentSeconds": 12000,
"id": "100028"
}
]
}
As I said, I want to put it in a list.
var json = client.MakeRequest("", password, user);
List<Worklog> myList = JsonConvert.DeserializeObject<List<Worklog>>(json);
It doesn't work, because of
"startAt": 0,
"maxResults": 1,
"total": 1,
How can I make the deserializer ignore those properties?
Thanks for your help!
Either create a "RootObject" class that does contain the properties:
public class RootObject
{
public int startAt { get; set; }
public int maxResults { get; set; }
public int total { get; set; }
public List<Worklog> worklogs { get; set; }
}
And deserialize into that:
var rootObject = JsonConvert.DeserializeObject<RootObject>(json);
// access rootObject.worklogs
Or step into the parsed JSON and deserialize from there:
JObject o = JObject.Parse(json);
JToken worklogsJson = o.SelectToken("worklogs");
var worklogs = worklogsJson.ToObject<List<Worklog>>();

Categories

Resources