I have this JSON and I cannot figure out how to convert it to a List of objects in C#.
Here is the JSON:
{
"2": {
"sell_average": 239,
"buy_average": 238,
"overall_average": 240,
"id": 2
},
"6": {
"sell_average": 184434,
"buy_average": 182151,
"overall_average": 189000,
"id": 6
},
"8": {
"sell_average": 11201,
"buy_average": 1723,
"overall_average": 180,
"id": 8
}
}
And the code I've tried using:
public class ItemSummaryModel
{
public string Id { get; set; }
public ItemSummary ItemSummary { get; set; }
}
public class ItemSummary
{
public int Sell_Average { get; set; }
public int Buy_Average { get; set; }
public int Overall_Average { get; set; }
public int Id { get; set; }
}
List<ItemSummaryModel> models =
JsonConvert.DeserializeObject<List<ItemSummaryModel>>(jsonSummary);
to no avail. How can I deserialize this JSON into lists of these objects using Newtonsoft's JSON library (Json.Net)?
You can use
var dict = JsonConvert.DeserializeObject<Dictionary<int, ItemSummary>>(json);
var items = dict.Values.ToList(); //if you want a List<ItemSummary>;
public class ItemSummaryModel
{
[JsonProperty(PropertyName = "2")]
public ItemSummary Two { get; set; }
[JsonProperty(PropertyName = "6")]
public ItemSummary Six { get; set; }
[JsonProperty(PropertyName = "8")]
public ItemSummary Eight { get; set; }
}
var result = JsonConvert.DeserializeObject<ItemSummaryModel>(json);
This will technically work to get you a complex object, but I don't much like it. Having numbers for property names is going to be an issue. This being json for a single complex object will also be tricky. If it were instead a list, you could begin writing your own ContractResolver to handle mapping the number property name to an id field and the actual object to whatever property you wanted.
Related
This question already has answers here:
Json.NET deserialize or serialize json string and map properties to different property names defined at runtime
(4 answers)
Closed last month.
I am writing a custom extension to DefaultContractResolver to map names between a JSON string and models to be deserialized.
The naming in these models is not consistent and I was specifically asked to not change them (renaming, adding attributes, etc).
The json looks like this
"parameter": {
"alarms": [
{
"id": 1,
"name": "alarm1",
"type": 5,
"min": 0,
"max": 2
}
],
"settings": [
{
"id": 1,
"name": "setting1",
"description": "something here"
"type": 1,
"value": 2
}
]
}
The Parameter class (output) has models for Alarms and Settings.
For example, these models look like this:
public class Alarm
{
public int AlarmId { get; set; }
public string AlarmName { get; set; }
public AlarmType RbcType { get; set; }
public int MinimumTolerated { get; set; }
public int MaximumTolerated { get; set; }
}
public class Setting
{
public int SettId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public SettingType Type { get; set; }
public int IntValue { get; set; }
}
As an example the value of "id" in the json can relate to AlarmId or SettId, so I cannot have just one resolver to perform the ResolvePropertyName(string propertyName)
And I don't know how to get about with this.
I don't think that you need any mapper, I would use this code
var jObj = JObject.Parse(json)["parameter"];
var parameters = new
{
alarms = jObj["alarms"].Select(x => new Alarm { AlarmId = (int)x["id"], AlarmName = (string)x["name"] }).ToList(),
settings = jObj["settings"].Select(x => new Setting { SettId = (int)x["id"] }).ToList()
};
I have a JSON file that looks something like this.
{
"id": "top1",
"components": [
{
"type": "resistor",
"id": "res1",
"resistance": {
"default": 100,
"min": 10,
"max": 1000
},
"netlist": {
"t1": "vdd",
"t2": "n1"
}
},
{
"type": "nmos",
"id": "m1",
"m(l)": {
"default": 1.5,
"min": 1,
"max": 2
},
"netlist": {
"drain": "n1",
"gate": "vin",
"source": "vss"
}
}
]
}
I want to make an API using oop to work with that JSON file,
I made the following classes.
public class Topology
{
[Required]
public string id { get; set; }
[Required]
public List<TopologyComponents> components { get; set; }
}
public class TopologyComponents
{
[Required]
public string type { get; set; }
[Required]
public string id { get; set; }
[Required]
public Values ???????? {get; set; }
[Required]
public Dictionary<string, string> netlist { get; set; }
}
public class Values
{
[Required]
public double #default { get; set; }
[Required]
public double min { get; set; }
[Required]
public double max { get; set; }
}
my question is those question marks????????
the field name is dynamic resistance, m(l), .....
how can I handle those cases?
I tried Jackson annotations, expandobject, and dictionaries. but none of them worked as I want.
From the looks of it, your Topology class will need to have Dictionary<string, dynamic> data type since the keys of components will be arbitrary. Even though type and id will be the same across all components, netlist and one other property will be dynamic.
Change your list of components to Dictionary<string, dynamic> and then get the data you need by first checking which property actually exists in the component.
public class Topology
{
[Required]
public string id { get; set; }
[Required]
public List<Dictionary<string, dynamic>> components { get; set; }
}
this will give you a list of dictionary with string as the keys and dynamic objects as the values. You can iterate through the keys using foreach loop on components.Keys and perhaps a switch statement to see if the key you expect exists when iterating through each component.
Example on how you can create your own list of components... not sure how you are going to use the data since that will drive the way you deserialize this,
var obj = JsonConvert.DeserializeObject<Topology>(jsonText);
List<dynamic> allComps = new List<dynamic>();
foreach(var component in obj.components)
{
var comp = new ExpandoObject() as IDictionary<string, object>;
foreach(var key in component.Keys)
{
switch (key)
{
case "id":
case "type":
comp.Add(key, component[key].ToString());
break;
case "netlist":
comp.Add(key, component[key].ToObject<Dictionary<string, string>>());
break;
default:
comp.Add(key, component[key].ToObject<Values>());
break;
}
}
allComps.Add(comp);
}
This question already has answers here:
How can I parse a JSON string that would cause illegal C# identifiers?
(3 answers)
Using JSON.NET to read a dynamic property name
(1 answer)
Create a strongly typed c# object from json object with ID as the name
(1 answer)
Closed 4 years ago.
I have a JSON string like this:
{
"ProfileChange": 5,
"profileId": "anId",
"profileChanges": [
{
"changeType": "fullProfileUpdate",
"profile": {
"_id": "g3fwerfgscsdadad",
"rvn": 7,
"wipeNumber": 5,
"accountId": "gw4gefsdfswfwfwdqe",
"profileId": "anId",
"version": "latestUpdate",
"items": {
"abc-123": {
"templateId": "default",
"attributes": {
"max": 0,
"bonus": 1,
"seen": 1,
"xp": 0,
"variants": [],
"favorite": false
},
"quantity": 1
},
"zxc-456": {
"templateId": "default",
"attributes": {
"max": 0,
"bonus": 1,
"seen": 1,
"xp": 0,
"variants": [],
"favorite": false
},
"quantity": 1
}
}
}
}
]
}
I want to deserialize it to a C# object, and here is my code:
class Model
{
[JsonProperty("ProfileChange")] public long ProfileChange { get; set; }
[JsonProperty("profileId")] public string ProfileId { get; set; }
[JsonProperty("profileChanges")] public List<ProfileChange> ProfileChanges { get; set; }
}
public class ProfileChange
{
[JsonProperty("changeType")] public string ChangeType { get; set; }
[JsonProperty("profile")] public Profile Profile { get; set; }
}
public class Profile
{
[JsonProperty("_id")] public string Id { get; set; }
[JsonProperty("rvn")] public long Rvn { get; set; }
[JsonProperty("wipeNumber")] public long WipeNumber { get; set; }
[JsonProperty("accountId")] public string AccountId { get; set; }
[JsonProperty("profileId")] public string ProfileId { get; set; }
[JsonProperty("version")] public string Version { get; set; }
[JsonProperty("items")] public Items Items { get; set; }
}
public class Items
{
public List<IDictionary<string, ItemDetails>> Item { get; set; }
}
public class ItemDetails
{
[JsonProperty("templateId")] public string TemplateId { get; set; }
}
And then I implement it in my main implementation like this:
var obj = JsonConvert.DeserializeObject<Model>(json);
And it does deserialize most of the data, however, the part I am struggling to deserialize is the Items one. Since they are generated dynamically, I want to create a dictionary of the items, with string for the entry and ItemDetails for the details of it.
I have used Dictionary and also made it a list, since there are multiple items, but it still is null. I also tried non-list, didn't return anything. Only null. All other details are fine, except the dictionary and dynamically generated JSON data.
I need help to fix the issue with deserializer returning null for the Items Dictionary.
I'm trying to deserialize an array using Newtonsoft so i can display files from a cloud based server in a listbox but i always end up getting this error no matter what i try:
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: [. Path '[0].priv', line 4, position 15.'
Thisis an example try to deserialize:
[
{
"code": 200,
"priv": [
{
"file": "file.txt",
"ext": "txt",
"size": "104.86"
},
{
"file": "file2.exe",
"ext": "exe",
"size": "173.74"
},
],
"pub": [
{
"file": "file.txt",
"ext": "txt",
"size": "104.86"
},
{
"file": "file2.exe",
"ext": "exe",
"size": "173.74"
}
]
}
]
I tried using a C# Class like this:
public class ListJson
{
[JsonProperty("pub")]
public List List { get; set; }
}
public class List
{
[JsonProperty("file")]
public string File { get; set; }
[JsonProperty("ext")]
public string Ext { get; set; }
[JsonProperty("size")]
public string Size { get; set; }
}
[JsonProperty("priv")]
public List List { get; set; }
}
public class List
{
[JsonProperty("file")]
public string File { get; set; }
[JsonProperty("ext")]
public string Ext { get; set; }
[JsonProperty("size")]
public string Size { get; set; }
}
And deserialize with:
List<list> fetch = Newtonsoft.Json.JsonConvert.DeserializeObject<List<list>>(json);
The correct C# class structure for your JSON is the following:
public class FileEntry
{
public string file { get; set; }
public string ext { get; set; }
public string size { get; set; }
}
public class FileList
{
public int code { get; set; }
public List<FileEntry> priv { get; set; }
public List<FileEntry> pub { get; set; }
}
Deserializing it in this way:
var fetch = JsonConvert.DeserializeObject<FileList[]>(json);
var fileList = fetch.First(); // here we have a single FileList object
As said in the other answer, creating a class called List doesn't automagically turn it into a collection of objects. You need to declare the types to be deserialized from an array a collection type (e.g. List<T>, T[], etc.).
Small tip: when in doubt, use json2csharp.com to generate strongly typed classes from a json string.
At the moment List has a single List instance called priv, which despite the name: doesn't make it a list. To deserialize a JSON array ("priv": [...]), it needs to an array or list-like type, for example List<T> for some T. Presumably a List<FileThing>, if we assume that FileThing is actually the second type called List (you have 2).
{"facet_counts":{
"facet_queries":{},
"facet_fields":{},
"facet_dates":{},
"facet_ranges":{
"createdat":{
"counts":[
"2015-05-17T00:00:00Z",155,
"2015-05-18T00:00:00Z",162,
"2015-05-19T00:00:00Z",200,
"2015-05-20T00:00:00Z",218,
"2015-05-21T00:00:00Z",181,
"2015-05-22T00:00:00Z",137],
"gap":"+1DAY",
"start":"2015-05-17T00:00:00Z",
"end":"2015-05-23T00:00:00Z"}}}}
I am trying to deserialize the above json into my object but the counts part is not getting deserialized. My object is
public class FacetCounts
{
public class Facet_Ranges
{
public class CreatedAt
{
public List<Counts> counts { get; set; }
public class Counts
{
public Dictionary<string, int> count { get; set; }
}
}
public CreatedAt createdat { get; set; }
}
public Facet_Ranges facet_ranges { get; set; }
}
I also tried removing the public Dictionary<string, int> count { get; set; } but still it fails.
My deserialize code is
objObject = JsonConvert.DeserializeObject<FacetCounts>(json);
Any help would be appreciated !!
public class FacetCounts
{
public class Facet_Ranges
{
public class CreatedAt
{
public List<string> counts
{
get
{
return Counts
.SelectMany(pair => new[]{pair.Key, pair.Value.ToString()})
.ToList();
}
set
{
var pairs = new Dictionary<string, int>();
for (var i = 0; i < value.Length / 2; ++i)
{
pairs[value[2*i]] = int.Parse(value[2*i+1]);
}
this.Counts = pairs;
}
}
[JsonIgnore]
public Dictionary<string, int> Counts {get;set;}
}
public CreatedAt createdat { get; set; }
}
public Facet_Ranges facet_ranges { get; set; }
}
Your JSon is invalid.
The error is the lack of braces around the complete JSon string {}
Here is a working JSon string:
{
"facet_counts": {
"facet_queries": {},
"facet_fields": {},
"facet_dates": {},
"facet_ranges": {
"createdat": {
"counts": [
"2015-05-17T00:00:00Z",
155,
"2015-05-18T00:00:00Z",
162,
"2015-05-19T00:00:00Z",
200,
"2015-05-20T00:00:00Z",
218,
"2015-05-21T00:00:00Z",
181,
"2015-05-22T00:00:00Z",
137
],
"gap": "+1DAY",
"start": "2015-05-17T00:00:00Z",
"end": "2015-05-23T00:00:00Z"
}
}
}
}
I used JSon Lint for validating your JSon, and fixed error by error.
I am not sure if your C# code is correct to Deserialize your JSon, so I would recommend you to use e.g. JSon2CSharp in order to create you JSon objects in C#. Then you can fix variable names, etc.
Surround each item in counts with {}
"facet_counts":{
"facet_queries":{},
"facet_fields":{},
"facet_dates":{},
"facet_ranges":{
"createdat":{
"counts":[
{"2015-05-17T00:00:00Z",155},
{"2015-05-18T00:00:00Z",162},
{"2015-05-19T00:00:00Z",200},
{"2015-05-20T00:00:00Z",218},
{"2015-05-21T00:00:00Z",181},
{"2015-05-22T00:00:00Z",137}],
"gap":"+1DAY",
"start":"2015-05-17T00:00:00Z",
"end":"2015-05-23T00:00:00Z"}}}
That isn't valid json - Your count objects need to be in {braces}.
FYI - You can also use json2csharp.com to auto-generate the c-sharp object to deserialize with, which would also highlight issues like this.
From JSON2CSHARP
public class Createdat
{
public List<object> counts { get; set; }
public string gap { get; set; }
public string start { get; set; }
public string end { get; set; }
}
This worked for me