How to deserialize dynamically named JSON in c#? - c#

I know there is a lot of similar questions and i tried to use it for last 12 h but without result. So please give me any advice how to solved my problem.
My json response look like this:
{
"status": "OK",
"products": {
"dynamic10259668": {
"ean": "4525348924",
"sku": "9384573245",
"name": "name1",
},
"dynamic10630436": {
"ean": "983623203943",
"sku": "9312763245",
"name": "name2"
},
"dynamic10634396": {
"ean": "1002904820",
"sku": "9384763245",
"name": "name3"
},
"dynamic10634398": {
"ean": "3400901100",
"sku": "9312763245",
"name": "name4"
},
"dynamic10634399": {
"ean": "8100103701",
"sku": "454763245",
"name": "name5"
},
"dynamic10634766": {
"ean": "5600904820",
"sku": "9384763245",
"name": "name6"
}
}
}
And models:
public class ProductsList
{
public string status { get; set; }
public ListProducts products { get; set; }
}
public class ListProducts
{
public ListProduct product { get; set; }
}
public class ListProduct
{
public string ean { get; set; }
public string sku { get; set; }
public string name { get; set; }
}
Now i need e.g. Directory<"dynamic10259668", "9384573245"> but don't know how to access to product value. I have try this code:
ProductsList productsList = JsonConvert.DeserializeObject<ProductsList>(response.Content);
foreach (ListProduct singleProduct in productsList.products.product)
{
Console.WriteLine(singleProduct.name);
}
My most common error is:
System.NullReferenceException: Object reference not set to an instance of an object.

You need to use a Dictionary<string, ListProduct>. I believe that will do what you want.
I kept your ListProduct class, but modified ProductsList to look like this:
public class ProductsList
{
public string status { get; set; }
public Dictionary<string, ListProduct> products { get; set; }
}
When I do that, this code properly deserializes your JSON:
var result = JsonConvert.DeserializeObject<ProductsList>(theJson);
You can get to the data for dynamic10259668 using something like:
if (result.products.TryGetValue("dynamic10259668", out var item))
{
Debug.WriteLine($"Name: {item.name}, Ean: {item.ean}, Sku: {item.sku}");
}

It looks like you were hoping for a dictionary of product name to ean. If that is all you need then the following code would work:
dynamic d = JObject.Parse(response.Content);
var productDictionary = new Dictionary<string, string>();
foreach (var product in d.products)
{
productDictionary[product.Name] = (string)product.Value.ean;
}

Related

Not getting result when deserializing json using DataContractJsonSerializer

I have following json:
{
"Australia": {
"count": 2,
"records": {
"File1.ppt": {
"id": "123456789"
},
"File2.doc": {
"id": "987654321"
}
}
},
"PDFs.zip": {
"count": 0,
"records": {}
},
"Peru": {
"count": 2,
"records": {
"File3.PPT": {
"id": "897456123"
},
"File4.PPT": {
"id": "123546789"
}
}
},
"total count": 4
}
and to deserialize the above json I have defined some classes so that I can use these classes while deserializing my json into objects and below are the classes:
namespace GEO_Batch_Creation
{
[DataContract]
class BhpIdJson
{
[DataMember(Name = "objects")]
public Dictionary<string, Country[]> Countries { get; set; }
[DataMember(Name = "total count")]
public int TotalCount { get; set; }
}
[DataContract]
class Country
{
[DataMember(Name = "count")]
public int Count { get; set; }
[DataMember(Name = "records")]
public Dictionary<string, Record> Records { get; set; }
}
[DataContract]
class Record
{
[DataMember(Name = "filename")]
public string FileName { get; set; }
[DataMember(Name = "id")]
public Dictionary<string, string> BhpId { get; set; }
}
}
But when I use following code to deserialize the json I am getting only total count.
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
// Deserialization from JSON
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(BhpIdJson));
BhpIdJson bsObj2 = (BhpIdJson)deserializer.ReadObject(ms);
}
Please suggest me where I am doing mistake.
I don't think that this JSON is in correct format. I don't know if you got this from somewhere or made for yourself, but if the last one I recommend you to change the structure.
Even in C# you cant realy create a class that has the objects and the count of the object in the same List or Array etc.
Based on your class your JSON yhould look like this:
{
"objects": [
{
"name": "Australia",
"count": 2,
"records": [
{
"fileName": "File1.ppt",
"id": "123456789"
},
{
"fileName": "File2.doc",
"id": "987654321"
}
]
}
],
"total count": 4
}
As you can see you have to add Name or something to your Country class. I hope it helped.
Edit:
You can create a list like I mentioned above but it's not a good practice I think.

Use Linq or C# to parse Json

I am getting familiar with C# and Linq and appreciate any help. It should be easy for someone who works with it. I have a Json object that returns contact information. I also have a list of ids. I need to compare the list to the Json object and wherever the value in the list matches the userclientcode in the Json object, I need to extract the following information (only for the matches):
clienttaxonomy (if not empty)
fullname (if not empty)
[0]contactdata ( -> email if not null or empty)
[1]contactdata (-> address if not null or empty)
[2]contactdata (-> phone number if not null or empty)
First List
var fileContactIds = new List<string> { "5678765", "2135123", "12341234", "341234123", "12341234123", "2341234123", "341234123", "123412341", "13342354",
"12342341", "123412322", "163341234", "2345234115", "8967896", "75626234 };
JSON object returned with:
return JsonConvert.DeserializeObject<RelatedContacts>(json)?.list;
This is the Json object:
[![Json object][1]][1]
This is the Json string (unescaped):
{
"type": "com.kurtosys.api.userprofile.domain.RelatedContactList",
"list": [{
"objectlistid": 5678765,
"objectlisttypeid": 4567876,
"objectlistname": "ALL.National",
"clienttaxonomyid": 765677,
"clienttaxonomy": "National Wholesaler",
"order": 1,
"contacts": [{
"personid": 7654345678,
"fullname": "Person Jallo",
"userid": 876567,
"userclientcode": "341234123",
"contactdetails": [{
"contactid": 8765567,
"contacttypeid": 4565,
"contactdata": "person.contact#site.com"
}, {
"contactid": 876545678,
"contacttypeid": 4565,
"contactdata": "Baltimore,MD,21209,United States"
}, {
"contactid": 87654567,
"contacttypeid": 4584,
"contactdata": "410-413-2640"
}]
}]
}, {
"objectlistid": 765678,
"objectlisttypeid": 40400461,
"objectlistname": "RM.Internal",
"clienttaxonomyid": 7567898,
"clienttaxonomy": "Internal Regional Wholesaler",
"order": 2,
"contacts": [{
"personid": 56789876,
"fullname": "Jackson Man",
"userid": 876567,
"userclientcode": "1012275",
"contactdetails": [{
"contactid": 309598309,
"contacttypeid": 76546,
"contactdata": "mister.jackson##site.com.com"
}, {
"contactid": 876567,
"contacttypeid": 4581,
"contactdata": "Baltimore,MD,21209,United States"
}, {
"contactid": 876567,
"contacttypeid": 2342,
"contactdata": "123-413-2604"
}]
}]
}, {
"objectlistid": 309571364,
"objectlisttypeid": 40400461,
"objectlistname": "RM.External",
"clienttaxonomyid": 309580710,
"clienttaxonomy": "External Regional Wholesaler",
"order": 3,
"contacts": [{
"personid": 302736188,
"fullname": "Phal Sumi",
"userid": 303826019,
"userclientcode": "163341234",
"contactdetails": [{
"contactid": 309598253,
"contacttypeid": 2342,
"contactdata": "misters.emailas#site.com"
}, {
"contactid": 309611930,
"contacttypeid": 2342,
"contactdata": "Baltimore,MD,21209,United States"
}, {
"contactid": 34234132,
"contacttypeid": 3422,
"contactdata": "342-803-1793"
}]
}]
}]
}
How do I
1] Select using Linq and Lambdas and put in a list fullname, email, address etc from the deserialized object ?
2]compare with first list and only transfer those items where the userclientcode == the number in list A.
I have tried:
var query5 = relatedContact.Where(s => s.objectlistid == Convert.ToInt64(contacts.Select(t => t.id)))
var selected = relatedContact.Where(p => p.contacts
.Any(a => fileContactIds.Contains(p.contacts))
.ToList();
var query2 = relatedContact.Where(s => s.objectlistid == Convert.ToInt64(contacts.Select(t => t.id)))
.Select(s => new
{
Description = s.clienttaxonomy,
Fullname = s.contacts[0].fullname,
Email = s.contacts[0].contactdetails[0].contactdata,
Address = s.contacts[0].contactdetails[1].contactdata,
PhoneNumber = s.contacts[0].contactdetails[2].contactdata
});
But don't really know what I'm doing it seems. Any suggestions on how to get the required sections ? I think part of the reason is that the contactdata is a list.
Thanks all
You can create a classes for the desearlization of JSON Object like this
public class Rootobject
{
public string type { get; set; }
public List[] list { get; set; }
}
public class List
{
public int objectlistid { get; set; }
public int objectlisttypeid { get; set; }
public string objectlistname { get; set; }
public int clienttaxonomyid { get; set; }
public string clienttaxonomy { get; set; }
public int order { get; set; }
public Contact[] contacts { get; set; }
}
public class Contact
{
public long personid { get; set; }
public string fullname { get; set; }
public int userid { get; set; }
public string userclientcode { get; set; }
public Contactdetail[] contactdetails { get; set; }
}
public class Contactdetail
{
public int contactid { get; set; }
public int contacttypeid { get; set; }
public string contactdata { get; set; }
}
And then to extract the selected information we can also create a another class like
public class ExtractedInfo
{
public string ocClientTaxonomy { get; set; }
public string ocFullName { get; set; }
public CTDetails ocContactDetails { get; set; }
}
public class CTDetails
{
public string ocCTAddress { get; set; }
public string ocCTEmail { get; set; }
public string ocCTPhoneNumber { get; set; }
}
Now we have to find all the data from JSON
var fileContactIds = new List<string> { "5678765", "2135123", "12341234", "341234123", "12341234123", "2341234123", "341234123", "123412341", "13342354", "12342341", "123412322", "163341234", "2345234115", "8967896", "75626234" };
//Read JSON from txt file. You can do it by your way
string myjson = File.ReadAllText("Some.txt");
string ctphno, ctadd, ctemail, cltax, ctfullname;
List<ExtractedInfo> ei = new List<ExtractedInfo>();
CTDetails ctdtl = new CTDetails();
ExtractedInfo eiex = new ExtractedInfo();
//Deserialize the JSON string to Object.
Rootobject AllData = JsonConvert.DeserializeObject<Rootobject>(myjson);
//Finding all data in List Class
foreach(List lst in AllData.list)
{
cltax = lst.clienttaxonomy; // you can directly put eiex.ocClientTaxonomy = lst.clienttaxonomy;
foreach(Contact ct in lst.contacts)
{
//To check if value in the list matches the objectlistid in the Json object
if(fileContactIds.Contains(lst.objectlistid.ToString()))
{
ctfullname = ct.fullname; // you can directly put eiex.ocFullName = ct.fullname;
foreach(Contactdetail ctd in ct.contactdetails)
{
//Here we are trying to find the Match for Email.
if(Regex.IsMatch(ctd.contactdata, #"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z", RegexOptions.IgnoreCase))
{
ctemail = ctd.contactdata;
ctdtl.ocCTEmail = ctemail;
}
//Here We trying to find the match for Phone Number.
else if(Regex.IsMatch(ctd.contactdata, #"\(?\d{3}\)?-? *\d{3}-? *-?\d{4}", RegexOptions.IgnoreCase))
{
ctphno = ctd.contactdata;
ctdtl.ocCTPhoneNumber = ctphno;
}
//If NOthing matches than it might be address (Assumed)
else
{
ctadd = ctd.contactdata;
ctdtl.ocCTAddress = ctadd;
}
}
eiex.ocFullName = ctfullname;
}
}
eiex.ocClientTaxonomy = cltax;
eiex.ocContactDetails = ctdtl;
ei.Add(eiex);
}
Hope this helps and fit in your requirements.

JSON Object from C#

I am trying to acheive below JSON Object from c# code
{
"Animals": {
"name": "Animals",
"data": [
[
"Cows",
2
],
[
"Sheep",
3
]
]
},
"Fruits": {
"name": "Fruits",
"data": [
[
"Apples",
5
],
[
"Oranges",
7
],
[
"Bananas",
2
]
]
},
"Cars": {
"name": "Cars",
"data": [
[
"Toyota",
1
],
[
"Volkswagen",
2
],
[
"Opel",
5
]
]
}
}
I tried json2C# link and it gave me this class structure
public class Animals
{
public string name { get; set; }
public List<List<object>> data { get; set; }
}
public class Fruits
{
public string name { get; set; }
public List<List<object>> data { get; set; }
}
public class Cars
{
public string name { get; set; }
public List<List<object>> data { get; set; }
}
public class RootObject
{
public Animals Animals { get; set; }
public Fruits Fruits { get; set; }
public Cars Cars { get; set; }
}
My first problem is the classes generated by code is static (Animals,Fruits,Cars) in reality it could be more and less it is category and it may be some new categories so every time I need to create a new class for each category? how can I handle this?
Second how I populate from these classes the same structure.
Please bear with me as I am very beginner level programmer.
Try this. Create a new console application. You will need the JSON.NET library.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
namespace ConsoleApplication7
{
class Item : List<object>
{
public Item()
{
this.Add(""); // for name;
this.Add(0); // for value;
}
[JsonIgnore]
public string Name { get { return this[0].ToString(); } set { this[0] = value; } }
[JsonIgnore]
public int Value { get { return (int)this[1]; } set { this[1] = value; } }
}
class Category
{
public string name { get; set; }
public List<Item> data { get; set; }
public Category()
{
this.data = new List<Item>();
}
}
class Program
{
static void Main(string[] args)
{
var all = new Dictionary<string, Category>
{
{
"Animals", new Category()
{
name = "Animals",
data =
new List<Item>()
{
new Item() {Name = "Cows", Value = 2},
new Item() {Name = "Sheep", Value = 3}
}
}
//include your other items here
}
};
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(all));
Console.ReadLine();
}
}
}
You don't need separate Animals, Fruits, etc. classes. They can be merged.
public class Category
{
public string name { get; set; }
public List<List<object>> data { get; set; }
}
And since the list of items in the root object can change, you should use a Dictionary<string, Category> instead of the RootObject class you had generated. Your JSON is not valid, (test it with http://jsonlint.com/), but this produces something like the first part of your example:
var dict = new Dictionary<string, Category>
{
{ "Animals", new Category
{
name = "Animals",
data = new List<List<object>>
{
new List<object> { "Cows", 2 },
new List<object> { "Sheep", 3 }
}
}
},
};
string serialized = JsonConvert.SerializeObject(dict, Formatting.Indented);
Produces the following (I'm using Json.NET for the serialization here). The other types would be similar. (see Object and Collection Initializers for more info on the list and dictionary initialization syntax I used, if you're unfamiliar with it; basically just shortcuts for their Add methods)
{
"Animals": {
"name": "Animals",
"data": [
[
"Cows",
2
],
[
"Sheep",
3
]
]
}
}
If you have a choice of what the data types should be, I think it'd be better to replace the List<object> with a class something like this, to be more clear:
public class Item
{
public string name { get; set; }
public int quantity { get; set; }
}
Install the JSON.NET library.
Then with the classes that were created:
string jsonStr = "{'Animals': {name: 'Animals', data: [['Cows', 2], ['Sheep', 3] ] },'Fruits': { name: 'Fruits', data: [['Apples', 5], ['Oranges', 7], ['Bananas', 2] ] }, 'Cars': { name: 'Cars', data: [ ['Toyota', 1], ['Volkswagen', 2], ['Opel', 5] ] } }";
RootObject Myobj = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(jsonStr);

How do I get a property from a list when parsing JSON in C# with JSON.NET?

I'm able to parse simple properties using JSON.NET with this C# code:
Code C#
WebClient c = new WebClient();
var data = c.DownloadString("http://localhost/json1.json");
JObject o = JObject.Parse(data);
listBox1.Items.Add(o["name"]);
listBox1.Items.Add(o["email"][0]);
listBox1.Items.Add(o["email"][1]);
listBox1.Items.Add(o["website"]["blog"]);
json1.json
{
"name": "Fname Lname",
"email": [
"email#gmail.com",
"email#hotmail.com"
],
"website":
{
"blog": "example.com"
}
}
json2.json
{
"name": "Fname Lname",
"email": [
"email#gmail.com",
"email#hotmail.com"
],
"website":
{
"blog": "example.com"
},
"faculty":
{
"department": [
{
"name": "department.name",
"location": "department.location"
}
]
}
}
From the second JSON file, I'm not able to get name and location from the department. How do I do that in C#?
name : department.name
location: department.location
yourjsonobject.faculty.department[0].name;
yourjsonobject.faculty.department[0].location;
Here is some jsfiddle to help you with this:
http://jsfiddle.net/sCCrJ/
var r = JSON.parse('{"name": "Fname Lname","email": [ "email#gmail.com", "email#hotmail.com"],"website":{ "blog": "example.com"},"faculty":{ "department": [ { "name": "department.name", "location": "department.location" } ]}}');
alert(r.faculty.department[0].name);
alert(r.faculty.department[0].location);
for (var i = 0; i < r.faculty.department.length; i++) {
alert(r.faculty.department[i].name);
}
Your problem is that department is an array of objects (though it happens to just contain one item here), but you're not accessing it like it is. You can use o["faculty"]["department"][0]["name"] to get your data.
You might want to use classes (here are ones auto-converted with http://json2csharp.com/) to more easily work with your data.
public class Website
{
public string blog { get; set; }
}
public class Department
{
public string name { get; set; }
public string location { get; set; }
}
public class Faculty
{
public List<Department> department { get; set; }
}
public class RootObject
{
public string name { get; set; }
public List<string> email { get; set; }
public Website website { get; set; }
public Faculty faculty { get; set; }
}
Then you can get all of the data (instead of hoping the fixed indexes are right, and that you didn't make a typo in the property names) with this code:
WebClient c = new WebClient();
var data = c.DownloadString("http://localhost/json1.json");
var o = JsonConvert.DeserializeObject<RootObject>(data);
listBox1.Items.Add(o.name);
foreach (var emailAddr in o.email)
listBox1.Items.Add(emailAddr);
listBox1.Items.Add(o.website.blog);
foreach (var dept in o.faculty.department)
{
listBox1.Items.Add(dept.name);
listBox1.Items.Add(dept.location);
}

How to deserialize json string in windows phone?

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.

Categories