I am trying to take the incoming JSON items and bind them to listbox items but I am told by visual studio that I need to do an Array and not Object? I've never had to do this... Anyone know how?
My RootObject:
public class RootObject
{
public string url { get; set; }
public string display { get; set; }
public List<string> genetics { get; set; }
public List<string> price { get; set; }
public List<string> brandMaker { get; set; }
public string form { get; set; }
public string dosornos { get; set; }
public string qty { get; set; }
public string mfg { get; set; }
public string mobURI { get; set; }
}
Note: Genetics, Price, BrandMaker don't actually return anything but a value, like below:
"genetics": [
"typeophere"
],
"price": [
"$1400"
],
JSON FILE/REQUEST BASIC RESULT:
[
{
"url": "N/A",
"display": "",
"genetics": [
"microogiz"
],
"price": [
"96.016"
],
"brandMaker": [
"Oshi Kunti Multikashi, Osaka, JP"
],
"form": "tangent",
"dosornos": "n/a",
"qty": "88G",
"mfg": "SelfMade Industries, USA Dist.",
"mobURI": "n/a"
}
]
My original code:
// Get JSON via WEB
string ProviderURI = goURI;
webClient webClient = new WebClient();
webClient.DownloadStringCompleted += new
DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadStringAsync(new Uri(ProviderURI));
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
{
return;
}
var deserializedJSON = JsonConvert.DeserializeObject<RootObject>(e.Result);
lstBoxResults.ItemsSource = deserializedJSON; // or deserializedJSON.url.ToString();
}
Ok, you mention that genetics and price are arrays, but the returned JSON only contains one item. The rest of your RootObject are simple string properties.
Since you did not post a raw JSON example. Let me present a trimmed down version, to keep things simple and short.
{
"url": "http://www.stackoverflow.com",
"display": "This is a test",
"genetics": [
"typeophere"
],
"price": [
"$1400"
],
"form": "a form"
}
Now we can trim down the RootObject class type. I used Pascal casing for my properties and attributed them with JSON.NET attributes to assist with the deserialing / serializing.
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class RootObject
{
[JsonProperty(PropertyName = "url")]
public string Url { get; set; }
[JsonProperty(PropertyName = "display")]
public string Display { get; set; }
[JsonProperty(PropertyName = "genetics")]
public List<string> Genetics { get; set; }
[JsonProperty(PropertyName = "price")]
public List<string> Price { get; set; }
[JsonProperty(PropertyName = "form")]
public string Form { get; set; }
}
Since I don't know the web service you are calling I just stored this JSON in a text file. Marked it as an embedded resource and read it from there.
string json;
var resource = Application.GetResourceStream(new Uri("json.txt", UriKind.Relative));
using (var reader = new StreamReader(resource.Stream))
{
json = reader.ReadToEnd();
}
Just replace this part with your WebClient call to obtain your JSON data.
Now we can deserialize the JSON into a RootObject instance.
var rootObject = JsonConvert.DeserializeObject<RootObject>(json);
Works as advertised. Now you need to bind it to a ListBox control. If you hover over the ItemSource property of your ListBox instance you'll see that the tooltip mentions that you can bind it to a collection. Well a single rootObject isn't a collection. You can't bind it directly.
lstBoxResults.ItemsSource = rootObject;
This will NOT work. You cannot convert a RootObject instance to a System.Collections.IEnumerable. Which is what ItemsSource is expecting.
Easy fix. Let's create a collection.
lstBoxResults.ItemsSource = new List<RootObject> { rootObject };
This is assuming that your JSON data only returns one rootObject. Only one item will appear in your ListBox.
Now let's suppose your JSON data returns an array of RootObjects. For example an array called "items" which contains a collection of RootItems.
{
"items": [
{
"url": "http://www.stackoverflow.com",
"display": "This is a test",
"genetics": [ "typeophere" ],
"price": [ "$1400" ],
"form": "a form"
},
{
"url": "https://github.com/geersch",
"display": "This is another test",
"genetics": [ "typeophere" ],
"price": [ "$2000" ],
"form": "another form"
}]
}
Deserialing this is equally easy. Using JSON.NET obtain the collection of RootObjects.
var data = JObject.Parse(json)["items"];
Now deserialize into a collection (IEnumerable).
var rootObjects = JsonConvert.DeserializeObject<IEnumerable<RootObject>>(data.ToString());
Since you now already have a collection of RootObject there is no need to create one yourself. You can directly bind it to the ListBox.
lstBoxResults.ItemsSource = rootObjects;
Seems like the JSON data you receive is invalid. Just before parsing it make sure you modify it so that you have a valid JSON object.
For example:
json = json.Substring(json.IndexOf("[") + 1);
json = json.Substring(0, json.LastIndexOf("]"));
var rootObjects = JsonConvert.DeserializeObject<RootObject>(json);
Try this
RootObject rootObject;
if (json.startsWith("["))
{
rootObject = JsonConvert.DeserializeObject<List<RootObject>>(json)[0];
}
else
{
rootObject = JsonConvert.DeserializeObject<RootObject>(json);
}
Related
I want to get data from json file correctly. The json data file I modeled for this is as follows:
{
"Free title 1":[
{
"Subject": "a1",
"Relation": "a2"
},
{
"Subject": "b1",
"Relation": "b2"
}
],
"Another free title":[
{
"Subject": "z1",
"Relation": "z2"
},
{
"Subject": "y1",
"Relation": "y2"
}
],
"Unordered title":[
{
"Subject": "x1",
"Relation": "x2"
},
{
"Subject": "w1",
"Relation": "w2"
}
]
}
This is how I create an object class:
public class _Infos_
{
public List<_Info_> Infos { get; set; }
}
public class _Info_
{
public string Subject { get; set; }
public string Relation { get; set; }
}
And finally I'm trying to get the data in a method like this:
var js = JsonConvert.DeserializeObject<_Infos_>(File.ReadAllText("__FILE_PATH__"));
foreach (var j in js.Infos)
{
MessageBox.Show(j.Subject);
}
I get the error that js is empty. Here I want to get Free title 1, Another free title and Unordered title in a list. Of course, these titles will be constantly changing. Afterwards, I want to get the Subject and Relation data under these titles. But I have no idea how to get it.
This data structure is a dictionary of collections of _Info_s. You need to deserialize it to Dictionary<string, List<_Info_>>.
Here are System.Text.Json and Json.net examples:
var d = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, List<_Info_>>>(json);
var d2 = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, List<_Info_>>>(json);
Your class definition is a little wrong.
You can use online tools "json to c#" to generate the correct classes.
like this one: https://json2csharp.com
Your "root" of your json for example does not contain an array in your json. The property "Free title 1":[..] is an array, so your root needs a property with the name FreeTitle1 and it has to be an array/list.
public class Root
{
[JsonProperty("Free title 1")]
public List<TitleInfo> FreeTitle1 { get; set; }
[JsonProperty("Another free title")]
public List<TitleInfo> AnotherFreeTitle { get; set; }
[JsonProperty("Unordered title")]
public List<TitleInfo> UnorderedTitle { get; set; }
}
public class TitleInfo
{
public string Subject { get; set; }
public string Relation { get; set; }
}
If your object members have dynamic names, you can also manually deserialize the object, e.g. using the general type JObject. E.g.
JObject obj = JObject.Parse(File.ReadAllText("__FILE_PATH__"));
JObject implements IEnumerable<KeyValuePair<string, JToken>> over which you can iterate.
Each member will then have JToken Value, which is a JArray in this case, which you can cast to a List of your type.
foreach (var groups in obj)
{
var infos = groups.Value.ToObject<List<_Info_>>();
// .. loop over infos
}
JSON
{
"count": 3,
"value": [
{
"id": "AAAAAAAAAAAAA",
"description": "test1",
"name": "name1"
},
{
"id": "BBBBBBBBBB",
"description": "test2",
"name": "name2"
},
{
"id": "CCCCCCCCCCCC",
"description": "test3",
"name": "name3"
}
]
}
I have a code in my solution retrieving from a LIST api and giving the JSON above.
How can I use a LINQ to retrieve specific values? (e.g) I need to select name1 and I will get the id,description,name values.
I am using a dynamic variable in my code:
dynamic json = JObject.Parse(client.GetString().Result);
I'd been tinkering with other online guides the past few hours. However, can't get the result right.
Please help.
One solution would be to deserialize your JSON string into C# objects and then use Linq to get a specific object.
C# class definitions:
public class Content
{
[JsonProperty("count")]
public int Count { get; set; }
[JsonProperty("value")]
public List<Value> Values { get; set; }
public Content()
{
Values = new List<Value>();
}
}
public class Value
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
Deserializing and getting the object:
string json = #"{
""count"": 3,
""value"": [
{
""id"": ""AAAAAAAAAAAAA"",
""description"": ""test1"",
""name"": ""name1""
},
{
""id"": ""BBBBBBBBBB"",
""description"": ""test2"",
""name"": ""name2""
},
{
""id"": ""CCCCCCCCCCCC"",
""description"": ""test3"",
""name"": ""name3""
}
]
}";
Content content = JsonConvert.DeserializeObject<Content>(json);
Value value = content.Values.FirstOrDefault(x => x.Name.Equals("name1", StringComparison.InvariantCultureIgnoreCase));
First, you can create a class to represent a client:
public class Client
{
public string Id { get; set; }
public string Description { get; set; }
public string Name { get; set; }
}
With this class, you can use JObject.Parse (as you're already doing) to parse the JSON into something that can be queried, use SelectToken to pull out the value array and then use ToObject to convert that to a list of Clients. Here's what that looks like:
var jsonObject = JObject.Parse(json_source);
var jsonObjectValue = jsonObject.SelectToken("value");
var clients = jsonObjectValue.ToObject<List<Client>>();
Once you've got your clients variable, you can use a simple LINQ statement to find the one that is name1:
var clientWithName1 = clients.SingleOrDefault(x => x.Name == "name1");
In this case, clientWithName will be null if no such client was found.
Here's a dotnetfiddle that demonstrates a complete solution.
Create an object Client that has properties id, description and name. Deserialize the json into a list of these objects.
List<Client> clients = JsonConvert.Deserialize<List<Client>>(json_source);
string desc = clients[0].description;
Apparently with fiddling with my code I found an answer for myself.
Thanks for to the ones trying to help me for giving me ideas.
var requestWorkProcess = await client.GetStringAsync("my url");
var workProcessId = JObject.Parse(requestWorkProcess)["value"].Children<JObject>().FirstOrDefault(o => o["name"].ToString() == workProcess).GetValue("id");
The JSON is coming in like this (pseudo code):
[{one-off intro object}, [{object},{object},{object}]]
So it's an array where the first thing in the array is an object I'm not interested in and the second is another array full of the objects I actually want to deserialize.
How can I do this with JSON.NET?
You can use Json.Net's LINQ-to-JSON API to do the job.
For sake of example, let's assume your JSON looks like this:
[
{
"blah": "nothing interesting here"
},
[
{
"id": 1,
"name": "foo",
"desc": "description of foo"
},
{
"id": 2,
"name": "bar",
"desc": "blurb about bar"
},
{
"id": 3,
"name": "baz",
"desc": "buzz about baz"
}
]
]
First, define a class to hold the items from the inner array that you're interested in.
public class Item
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("desc")]
public string Description { get; set; }
}
Now, all you need to do is parse the JSON to a JArray, then get the child array from that and use ToObject() to convert it to a list of items.
JArray ja = JArray.Parse(json);
List<Item> list = ja[1].ToObject<List<Item>>();
From there, you can use the list of items as you normally would.
Fiddle: https://dotnetfiddle.net/CaFzux
You can get to the second set of objects either via strongly typed casting or dynamically, here is an example of doing it dynamically:
dynamic jsonArray = JArray.Parse(json);
dynamic targetJsonObjects = jsonArray[1];
Have you tried just simple model like this?
public class RootObject
{
public object IntroObject { get; set; }
public List<Item> Items { get; set; }
}
public class Item
{
public string WhatEverPropertyYouNeed{ get; set; }
}
I just got my json response as a string.My json is given below,
"code": 0,
"message": "success",
"students": {
"details":{
"hjeke": {
"id": "257633000000070001",
"name": "hjeke",
"percentage": 36,
"type": "Good",
},
"Second": {
"id": "257633000000073001",
"name": "Second",
"percentage": 4,
"type": "bad",
}
}
}
Like hjeke and Second there are many key value pairs,how can i deserialize my json using Newtonsoft.json
Try to understand my solution in your previous question
How to deserialize json data in windows phone?
Your first JSON in that question was good and simple to use.
JSON, where field names are unique not convinient to deserialize. So, you got problems such as public class Hjeke and public class Second for each instance, when you use code generator.
Use JSON-structure with list of students:
"code": 0,
"message": "success",
"students": [
{
"id": "257633000000070001",
"name": "hjeke",
"percentage": 36,
"type": "Good",
},
{
"id": "257633000000073001",
"name": "Second",
"percentage": 4,
"type": "bad",
}]
is good and flexible structure. Using this, you don't need to parse not obvious fields like
"details":{
"hjeke": {
and so on.
And work with them using classes, from my previous answer. The main idea - you need list of objects. public List<StudentDetails> students. Then, all students objects deserialized in List, which is easy to use.
As everybody mentioned your json seems to be very unflexible, huh.
You can extract the data you are interested in.
So this is your model:
public class StudentDetails
{
public string id { get; set; }
public string name { get; set; }
public int percentage { get; set; }
public string type { get; set; }
}
And this is how you can extract it:
var jsonObj = JObject.Parse(str);
// get JSON result objects into a list
var results = jsonObj["students"]["details"].Children().Values();
// serialize JSON results into .NET objects
var details = new List<StudentDetails>();
foreach (JToken result in results)
{
var st = result.ToString();
var searchResult = JsonConvert.DeserializeObject<StudentDetails>(st);
details.Add(searchResult);
}
I'm using a newtonsoft.json library here.
Your Response string has some mistakes man, its not a valid json
just small modification to be done as below:
{
"code": 0,
"message": "success",
"students": {
"details": {
"hjeke": {
"id": "257633000000070001",
"name": "hjeke",
"percentage": 36,
"type": "Good"
},
"Second": {
"id": "257633000000073001",
"name": "Second",
"percentage": 4,
"type": "bad"
}
}
}
}
you can make out the difference
Now Follow these steps:
1.Go to this link Json to C#
2.place your Json string there and generate C# class object
3.Now create this class in your solution
4.Now deserialize As below
var DeserialisedObject = JsonConvert.DeserializeObject<Your Class>(YourJsonString);
First, create the classes:
public class Hjeke
{
public string id { get; set; }
public string name { get; set; }
public int percentage { get; set; }
public string type { get; set; }
}
public class Second
{
public string id { get; set; }
public string name { get; set; }
public int percentage { get; set; }
public string type { get; set; }
}
public class Details
{
public List<Hjeke> hjeke { get; set; }
public List<Second> Second { get; set; }
}
public class Students
{
public List<Details> details { get; set; }
}
public class RootObject
{
public int code { get; set; }
public string message { get; set; }
public List<Students> students { get; set; }
}
After that, use JSON.NET to deserialize:
var deserialized = JsonConvert.DeserializeObject<Class1>(YourStringHere);
Do you have any influence over the json response? Details should probably be a JSONArray in this case, not an object with a varying amount of properties, since I assume that's what you mean is the issue here.
json ="{
"data": [
{
"id": "1000",
"from": {
"name": "Anthony Waema",
"category": "message",
"id": "192"
},
"message": "this is the message",
"updated_time": "2001-05-06T19:34:15+0000",
"likes": {
"data": [
{
"id": "100001692250255",
"name": "\u00dcnal Turanl\u0131"
},
{
"id": "100001060078996",
"name": "S\u00e9f\u00e2 K\u00e2ql\u00e4Nn"
}]
},
{
"id": "10150186255753553",
"from": {
"name": "another name",
"category": "message",
"id": "100001"
},
"message": "this is the message",
"updated_time": "2001-04-06T19:34:15+0000",
"likes": {
"data": [
{
"id": "1002345",
"name": "\u00dcnal Turanl\u0131"
},
{
"id": "100234",
"name": "S\u00e9f\u00e2 K\u00e2ql\u00e4Nn"
}]
}
}
]
}";
public class Allstatus
{
public List<sdata> data { get; set; }
public scpaging paging { get; set; }
}
public class sdata
{
public string id { get; set; }
public sfrom from { get; set; }
public string message { get; set; }
public string updated_time {get; set;}
public List<likesdata> likes { get; set; }
}
public class likesdata
{
public string id{ get; set; }
public string name{ get; set; }
}
public class sfrom
{
public string name {get; set;}
public string category {get; set;}
public string id {get; set;}
}
JavaScriptSerializer ser = new JavaScriptSerializer();
page = ser.Deserialize<allstatus>(json);
foreach (sdata cd in page.data)
{
foreach(likesdata ld in cd.likes.data)
{
Console.WriteLine(ld.id+"\t"+ld.name);
}
}
problem:
I need to parse the json and retrieve likes data.
I can access "from" data but not "likes" data.. I get nullreference error when I do this. help needed here.. Thanks.
Edit2:
Referring https://gist.github.com/973510, its clear from the returned json, that if a particular facebook message doesnt have any likes, then the returned json doesnt contain a property called likes. Hence likes property of sdata object is null. Thats just how the server returns the data.
There are two ways you can deal with this. Either do a manual check whether likes is null. Or initialize the likes property in the sdata constructor. And initialize the likesdata list in the likesdatacollection constructor.
Code:
public class sdata
{
// other properties
public likedatacollection likes { get; set; }
public sdata()
{
likes = new likedatacollection();
}
}
public class likedatacollection
{
public List<likesdata> data { get; set; }
public likedatacollection()
{
data = new List<likesdata>();
}
}
This way, even if fb doesnt return any likes, the constructors will initialize the properties, so they will not be null. You can then check whether likes.data.Count > 0. If yes, then fb returned likes, else fb didnt return likes.
Edit1:
From the OP's comment, its clear that the json is properly formed. Meaning, the json is as retrieved from some server api. Therefore it is the sdata class that is the culprit. Please look at this gist for the full solution.
The short version. For the simplest case, your c# classes need to follow the exact same structure as your json. As per the json, data has a property called likes. the likes object has a property called data which is an array of objects with properties id and name.
So your c# class sdata should have a property called likes of type likesdatacollection. This class should have a property data of type List<likesdata>...
Off topic, people generally seem to prefer Json.Net ... so you may want to use that. The reason I use it is because I need it to work in a .Net 2.0 code base ...
You should try running your JSON through a validator like JSON Lint. That should help you find any JSON errors.