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);
Related
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;
}
I have below json which I need to deserialize in C# -
{
"clientSettings":[
{
"clientId":12345,
"entries":[
{
"key":"abc",
"value":false
},
{
"key":"def",
"value":false
},
{
"key":"ghi",
"value":false
}
]
},
{
"clientId":9876,
"entries":[
{
"key":"lkmn",
"value":false
}
]
}
],
"productSettings":[
{
"productId":11,
"entries":[
{
"key":"jkl",
"value":true
},
{
"key":"mno",
"value":true
}
]
},
{
"productId":12,
"entries":[
{
"key":"jkl",
"value":true
},
{
"key":"mno",
"value":true
}
]
}
],
"customerSettings":[
{
"key":"enableData",
"value":false
},
{
"key":"minPriceValue",
"value":"10.28"
},
{
"key":"presentData",
"value":"AEGIS"
}
],
"thothTest":{
"9876":[
"K"
],
"5431":[
"A",
"L"
],
"5123":[
"L"
]
},
"osirisTest":{
"7678":[
"K"
]
}
}
Below is the classes I created to deserialzie json into -
public class ProcessHolder : Holder
{
public IDictionary<int, ISet<string>> OsirisTest { get; set; }
public IDictionary<int, ISet<string>> ThothTest { get; set; }
}
public class Holder
{
public IList<Mapping> CustomerSettings { get; set; }
public IList<ClientSettingsMapping> ClientSettings { get; set; }
public IList<ProductSettingsMapping> ProductSettings { get; set; }
}
public class Mapping
{
public string Key { get; set; }
public object Value { get; set; }
}
public class ProductSettingsMapping : Mapping
{
public int ProductId { get; set; }
}
public class ClientSettingsMapping : Mapping
{
public int ClientId { get; set; }
}
I want to load all customerSettings values into CustomerSettings object of Holder class.
Similarly I want to load all clientSettings values into ClientSettings object of Holder class.
Similarly all productSettings values into ProductSettings object of Holder class.
Similarly thothTest values into ThothTest and osirisTest values into OsirisTest object.
I was trying with below code but somehow I am not able to see Key and Value variables being populated inside Mapping class object after deserializing my above json.
private static readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
public static void Main(string[] args)
{
var jsonContent = File.ReadAllText("/beta/Downloads/test.json");
var config = JsonConvert.DeserializeObject<ProcessHolder>(jsonContent, serializerSettings);
if (config == null)
{
Console.WriteLine("Some Parsing Issue");
}
// using config object here
}
What is wrong I am doing here? I just need to deserialize my json into above classes and give me ProcessHolder object back which I can use later on.
Looking at your JSON, clientSettings and productSettings have entries array. There is no corresponding matching property in your class definition for same.
I would suggest to modify your class definition as per JSON. Try below and see if it helps:
public class ProductSettingsMapping
{
public int ProductId { get; set; }
public IList<Mapping> Entries { get; set; }
}
public class ClientSettingsMapping
{
public int ClientId { get; set; }
public IList<Mapping> Entries { get; set; }
}
Second option - if you are not able to modify classes, you can amend JSON. I am providing sample for clientSettings
{
"clientSettings": [
{
"clientId": 12345,
"key": "abc",
"value": false
},
{
"clientId": 12345,
"key": "def",
"value": false
},
{
"clientId": 12345,
"key": "ghi",
"value": false
},
{
"clientId": 9876,
"key": "lkmn",
"value": false
}
]
}
You can update productSettings accordingly.
Third option is to parse into JObject and then convert to your classes.
A sample for clientSettings
static void Main(string[] args)
{
var json = "{'clientSettings':[{'clientId':12345,'entries':[{'key':'abc','value':false},{'key':'def','value':false},{'key':'ghi','value':false}]},{'clientId':9876,'entries':[{'key':'lkmn','value':false}]}],'productSettings':[{'productId':11,'entries':[{'key':'jkl','value':true},{'key':'mno','value':true}]},{'productId':12,'entries':[{'key':'jkl','value':true},{'key':'mno','value':true}]}],'customerSettings':[{'key':'enableData','value':false},{'key':'minPriceValue','value':'10.28'},{'key':'presentData','value':'AEGIS'}],'thothTest':{'9876':['K'],'5431':['A','L'],'5123':['L']},'osirisTest':{'7678':['K']}}";
var parsed = JObject.Parse(json);
var parsedClientSettings = parsed["clientSettings"];
List<ClientSettingsMapping> clientSettings = new List<ClientSettingsMapping>();
foreach (var parsedClientSetting in parsedClientSettings)
{
var clientId = parsedClientSetting.Value<int>("clientId");
foreach (var entry in parsedClientSetting["entries"])
{
clientSettings.Add(new ClientSettingsMapping { ClientId = clientId, Key = entry["key"].ToString(), Value = entry["value"].ToString() });
}
}
ProcessHolder processHolder = new ProcessHolder() { ClientSettings = clientSettings };
Console.ReadLine();
}
You should define "entries" in both ProductSettingsMapping and ClientSettingsMapping class.
public class ProductSettingsMapping
{
public int ProductId { get; set; }
public IList<Mapping> entries { get; set; }
}
public class ClientSettingsMapping
{
public int ClientId { get; set; }
public IList<Mapping> entries { get; set; }
}
I'm trying to format a List object to JSON in a specific way:
...
{
"MyList": [
"Entry": {
"Id": "1000",
"Name" : "Billy"
}
]
}
...
My problem is that I can't get the "Entry" property name to be written per item in the list.
Here's my C# code:
Entry.cs
[JsonObject(MemberSerialization.OptIn)]
public class Entry
{
[JsonProperty]
public string Id { get; set; }
[JsonProperty]
public string Name { get; set; }
}
List.cs
[JsonObject(MemberSerialization.OptIn)]
public class MyList
{
[JsonProperty]
List<Entry> List = new List<Entry>();
public void Add(Entry param) {
List.Add(param);
}
}
TestController.cs
[HttpPost]
public IHttpActionResult GrabarMarcacion([FromBody] JObject data)
{
MyList lst = new MyList();
lst.Add(new Entry{Id="1000", Name="Billy"});
return Ok(lst);
}
I'm sorry I'm new to JSON and REST, is it even possible to do what I ask? so far I always get something like:
{
"List": {
{
"ID": "1000",
"Name" : "Billy"
},
{
"ID": "1001",
"Name" : "Bob"
}
}
}
I have never used c# but try for Entry.cs :
[JsonObject(MemberSerialization.OptIn)]
public class Entry
{
[JsonProperty]
public object Entry { get; set; }
{
[JsonProperty]
public string Id { get; set; }
[JsonProperty]
public string Name { get; set; }
}
}
From what I understand, you want Entry property name for every item in the list. The simplest way to do this would be by making it a Dictionary:
Renamed Entry.cs to EntryModel.cs
[JsonObject(MemberSerialization.OptIn)]
public class EntryModel
{
[JsonProperty]
public Dictionary<string, string> Entry { get; set; }
}
In List.cs, change the property to MyList. This requires a change to the class name.
[JsonObject(MemberSerialization.OptIn)]
public class MyListModel
{
[JsonProperty]
public List<EntryModel> MyList { get; set; } = new List<EntryModel>();
}
Now in your TestController.cs, you may use:
MyListModel lst = new MyListModel();
lst.MyList.Add(new EntryModel
{
Entry = new Dictionary<string, string> {
{ "Id", "1000" }, { "Name", "Billy" } }
});
lst.MyList.Add(new EntryModel
{
Entry = new Dictionary<string, string> {
{ "Id", "3000" }, {"Name", "ABC" } }
});
This gives the following JSON:
{
"MyList": [
{
"Entry": {
"Id": "1000",
"Name": "Billy"
}
},
{
"Entry": {
"Id": "3000",
"Name": "ABC"
}
}
]
}
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.
I would like to deserialize a JSON string which contains multiple object types. So for instance here are my two POCO classes:
public class Car
{
[Key]
public int Id { get; set; }
public string Color { get; set; }
}
public class Driver
{
[Key]
public int Id { get; set; }
public string Firstname { get; set; }
}
Now I would like to have a JSON string which would have an array of objects from both classes (which are unrelated) and that would get deserialized into their respective POCO classes using the Newtonsoft json package in Visual Studio.
Is this possible and if so, what does the JSON format look like? An example would be appreciated with just 2 objects per class to show the array of objects and the two class types coexisting within a single JSON string which is passed to something like JsonConvert.DeserializeObject.
EDIT: the JSON for these classes and an object within would individually look something like:
for Car...
[
{
"color": "red"
},
{
"color": "blue"
}
]
and for Driver...
[
{
"Firstname": "Fred"
},
{
"Firstname": "Sally"
}
]
But now could those be combined into one string, but with some sort of extra parm to define to which CLASS each set belongs such as:
"Car"
[
{
"color": "red"
},
{
"color": "blue"
}
],
"Driver"
[
{
"Firstname": "Fred"
},
{
"Firstname": "Sally"
}
]
See how this has 2 unrelated classes in a single JSON string? Now I'd like to do a single (if possible) Jsonconvert into the respective classes so that "Car" winds up with 2 objects and "Driver" winds up with 2 (for this example).
Could be done like this:
using System.Collections;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var objArray = new ArrayList
{
new Car {Id = 1, Color = "blue"},
new Driver {Id = 1, Firstname = "John"},
new Car {Id = 2, Color = "blue"},
new Driver {Id = 2, Firstname = "Jane"}
};
var json = JsonConvert.SerializeObject(objArray);
var jArray = JArray.Parse(json);
foreach (var child in jArray.Children())
{
if (child.Children().Any(token => token.Path.Contains("Color")))
{
// we got a Car
var car = ((JObject) child).ToObject<Car>();
}
else if (child.Children().Any(token => token.Path.Contains("Firstname")))
{
// we got a Driver
var driver = ((JObject) child).ToObject<Driver>();
}
}
}
}
public class Car
{
public int Id { get; set; }
public string Color { get; set; }
}
public class Driver
{
public int Id { get; set; }
public string Firstname { get; set; }
}
}