Deserialize Complex JSON - c#

I am trying to deserialize the following JSON String:
Link to JSON String
{
"result": 1,
"error": null,
"id": 0,
"data": {
"ASTEALTHYNODE01_0301_0_30": {
"css_class": "sensor rf digital humidity",
"default_name": "Humidity",
"device_type": "humidity",
"did": "30",
"gid": "0301",
"has_subdevice_count": 0,
"has_time_series": 1,
"is_actuator": 0,
"is_sensor": 1,
"is_silent": 0,
"last_data": {
"DA": 58,
"timestamp": 1355791804474
},
"meta": {},
"node": "ASTEALTHYNODE01",
"shortName": "Humidity",
"subDevices": {},
"vid": "0"
},
"ASTEALTHYNODE01_0301_0_31": {
"css_class": "sensor rf digital temperature",
"default_name": "Temperature",
"device_type": "temperature",
"did": "31",
"gid": "0301",
"has_subdevice_count": 0,
"has_time_series": 1,
"is_actuator": 0,
"is_sensor": 1,
"is_silent": 0,
"last_data": {
"DA": 26.6,
"timestamp": 1355791804475
},
"meta": {},
"node": "ASTEALTHYNODE01",
"shortName": "Temperature",
"subDevices": {},
"vid": "0"
},
"ASTEALTHYNODE01_0_0_1000": {
"css_class": "actuator cape led rgbled",
"default_name": "On Board RGB LED",
"device_type": "rgbled",
"did": "1000",
"gid": "0",
"has_subdevice_count": 0,
"has_time_series": 0,
"is_actuator": 1,
"is_sensor": 1,
"is_silent": 0,
"last_data": {
"DA": "22B42B",
"timestamp": 1355790209080
},
"meta": {},
"node": "ASTEALTHYNODE01",
"shortName": "On Board RGB LED",
"subDevices": {},
"vid": "0"
},
"ASTEALTHYNODE01_0_0_11": {
"css_class": "sensor serial rf rf433 receiver transmitter",
"default_name": "RF 433Mhz",
"device_type": "rf433",
"did": "11",
"gid": "0",
"has_subdevice_count": 1,
"has_time_series": 0,
"is_actuator": 1,
"is_sensor": 1,
"is_silent": 0,
"last_data": {
"DA": "010001010101010100010101",
"timestamp": 1355789891324
},
"meta": {},
"node": "ASTEALTHYNODE01",
"shortName": "RF 433Mhz",
"subDevices": {
"6l8At": {
"category": "rf",
"data": "011111110001010100110000",
"shortName": "Door Bell",
"type": "sensor"
}
},
"vid": "0"
}
}
}
I usually create the classes with help of: http://json2csharp.com and then I am doing something like this (Json.NET libary):
Collapse | Copy Code
var result = JsonConvert.DeserializeObject<MyObject>(jsonString);
But the number of devices and their names (example: ASTEALTHYNODE01_0_0_11) are unknown before I get the JSON string. How can i deserialize this ?
Thank you

This works for me, with your JSON, and using JSON.NET:
Payload payloadJsonNet = JsonConvert.DeserializeObject<Payload>(data);
System.Diagnostics.Debug.Assert
(
payloadJsonNet.data.ContainsKey("ASTEALTHYNODE01_0_0_11") &&
payloadJsonNet.data["ASTEALTHYNODE01_0_0_11"].subDevices.ContainsKey("6l8At") &&
payloadJsonNet.data["ASTEALTHYNODE01_0_0_11"].subDevices["6l8At"].shortName == "Door Bell"
);
... provided you have prepared the following POCOs (using the nifty json2csharp helper, for example):
public class Payload
{
public int result { get; set; }
public int id { get; set; }
public Error error { get; set; }
public Dictionary<string, Device> data { get; set; }
}
public class Device
{
public string css_class { get; set; }
public string default_name { get; set; }
public string device_type { get; set; }
public string did { get; set; }
public string gid { get; set; }
public int has_subdevice_count { get; set; }
public int has_time_series { get; set; }
public int is_actuator { get; set; }
public int is_sensor { get; set; }
public int is_silent { get; set; }
public LastData last_data { get; set; }
public Meta meta { get; set; }
public string node { get; set; }
public string shortName { get; set; }
public Dictionary<string, Device> subDevices { get; set; }
public string vid { get; set; }
}
public class LastData
{
public string DA { get; set; }
public long timestamp { get; set; }
}
public class Meta
{
}
public class Error
{
}
I guess you'll have to find out / infer from other JSON inputs what should be the properties for these last two guys (i.e., "Meta" and "Error").
Note also, the "long" type that needs to be used in:
public class LastData
{
public string DA { get; set; }
public long timestamp { get; set; }
}
Finally, just for the curious, my own parser deserializes it fine as well:
Payload payloadMyParser = new JsonParser().Parse<Payload>(data);
System.Diagnostics.Debug.Assert
(
payloadMyParser.data.ContainsKey("ASTEALTHYNODE01_0_0_11") &&
payloadMyParser.data["ASTEALTHYNODE01_0_0_11"].subDevices.ContainsKey("6l8At") &&
payloadMyParser.data["ASTEALTHYNODE01_0_0_11"].subDevices["6l8At"].shortName == "Door Bell"
);
'Hope this helps,

Your json "data" property looks like property with type Dictionary < string, SomeClass>, where SomeClass - is a class for
{
"css_class": "sensor rf digital humidity",
// skipped
"subDevices": {},
"vid": "0"
},
data structure, so you may define this property in MyObject class and use strong typed deserialization without any problem.

Related

The JSON value could not be converted to System.Collections.Generic.List

I am trying to make a list of all items in the game using System.Text.Json;
I am very new to using .json files
I have tried doing this to test if it works:
List<Item> AllItems = new List<Item>();
string json = File.ReadAllText("Items.json");
AllItems = Deserialize<List<Item>>(json);
WriteLine(AllItems[0].Name);
It doesnt let me Convert It into a list
This is the json file
{
"Item": [
{
"Weapon": [
{
"CritChance": 60,
"HitChance": 80,
"OGDamge": 15,
"Damage": 15,
"Damage_Type": "Physical",
"Weapon_Type": "Fist",
"Player": null,
"APUsage": 4,
"ID": 1,
"Name": "Debug",
"Value": 16,
"Rarity": "Common",
"Item_Type": "Weapon"
},
{
"CritChance": 40,
"HitChance": 70,
"OGDamge": 15,
"Damage": 15,
"Damage_Type": "Electric",
"Weapon_Type": "Bow",
"Player": null,
"APUsage": 5,
"ID": 2,
"Name": "Debug2",
"Value": 15,
"Rarity": "Common",
"Item_Type": "Weapon"
}
]
}
]
}
Can anyone help me out :)
Your json file starts with curly braces that means you need parent class that contains list of Item named Item,
Or you just change your json file, starts with [ bracket
that means your main object is collection.
The code below does not use the file you use but a string with (almost) the same contents. You need to declare classes for every item in your Json before you can deserialize with in this case NewtonSoft.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace JsonDeserialize
{
class Program
{
static void Main(string[] args)
{
var json = #"
{
'Items': [
{
'Weapons': [
{
'CritChance': 60,
'HitChance': 80,
'OGDamge': 15,
'Damage': 15,
'Damage_Type': 'Physical',
'Weapon_Type': 'Fist',
'Player': null,
'APUsage': 4,
'ID': 1,
'Name': 'Debug',
'Value': 16,
'Rarity': 'Common',
'Item_Type': 'Weapon'
},
{
'CritChance': 40,
'HitChance': 70,
'OGDamge': 15,
'Damage': 15,
'Damage_Type': 'Electric',
'Weapon_Type': 'Bow',
'Player': null,
'APUsage': 5,
'ID': 2,
'Name': 'Debug2',
'Value': 15,
'Rarity': 'Common',
'Item_Type': 'Weapon'
}
]
}
]
}";
var allItems = JsonConvert.DeserializeObject<AllItems>(json);
Console.WriteLine(allItems.Items[0].Weapons[0].Name);
Console.ReadKey();
}
}
public class AllItems
{
public List<Item> Items { get; set; }
}
public class Item
{
public List<Weapon> Weapons { get; set; }
}
public class Weapon
{
public int CritChance { get; set; }
public int HitChance { get; set; }
public int OGDamge { get; set; }
public int Damage { get; set; }
public string Damage_Type { get; set; }
public string Weapon_Type { get; set; }
public string Player { get; set; }
public int APUsage { get; set; }
public string ID { get; set; }
public string Name { get; set; }
public int Value { get; set; }
public string Rarity { get; set; }
public string Item_Type { get; set; }
}
}
What always helps me in these cases is using the 'dynamic' keyword like so:
dynamic allItems = JsonConvert.DeserializeObject<dynamic>(json);
You can see what is deserialized using the 'locals'

c# how to count the amount of json values

So, I am trying to count the amount of values in JSON using c#. The Json is:
{
"Someid": 657442,
"roles": [
{
"id": 3892751,
"name": "Guest",
"rank": 0,
"memberCount": 0
},
{
"id": 3892750,
"name": "Fanz!<3",
"rank": 1,
"memberCount": 0
},
{
"id": 3892749,
"name": "Lead-Singer",
"rank": 254,
"memberCount": 0
},
{
"id": 3892748,
"name": "Drums",
"rank": 255,
"memberCount": 0
}
]
}
I want to count the amount "roles". The JSON is just in a string variable. Help?
You can either use like this:
var token = JToken.Parse(input);
var roles= token.Value<JArray>("roles");
var count = roles.Count;
Or you can also use JsonPath:
var token = JToken.Parse(input);
var count = token.SelectTokens("$.roles[*]").Count();
But ideally, you should be serilizing into an object and then using the properties to get the Count:
public class Role
{
public int id { get; set; }
public string name { get; set; }
public int rank { get; set; }
public int memberCount { get; set; }
}
public class MyObject
{
public int Someid { get; set; }
public List<Role> roles { get; set; }
}
var item = JsonConvert.DeserializeObject<MyObject>(input);
var count = item.roles.Count;

C# - Parse and read the JSON which has duplicate Keys

I am trying to figure out how I can parse the below JSON and get the "text": "lawyer" out of it. I see that it has to many branching. i.e Arrays and Objects. I want to do this in C#. Here is the JSON:
{
"status": "Succeeded",
"succeeded": true,
"failed": false,
"finished": true,
"recognitionResult": {
"lines": [{
"boundingBox": [140, 289, 818, 294, 816, 342, 138, 340],
"text": "General information Com",
"words": [{
"boundingBox": [106, 290, 363, 291, 363, 343, 106, 343],
"text": "General"
}, {
"boundingBox": [323, 291, 659, 291, 659, 344, 323, 343],
"text": "lawyer"
}, {
"boundingBox": [665, 291, 790, 291, 790, 344, 665, 344],
"text": "Com"
}]
}]
}
}
First use Quicktype.io to generate a native C# class:
public partial class Result
{
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("succeeded")]
public bool Succeeded { get; set; }
[JsonProperty("failed")]
public bool Failed { get; set; }
[JsonProperty("finished")]
public bool Finished { get; set; }
[JsonProperty("recognitionResult")]
public RecognitionResult RecognitionResult { get; set; }
}
public partial class RecognitionResult
{
[JsonProperty("lines")]
public Line[] Lines { get; set; }
}
public partial class Line
{
[JsonProperty("boundingBox")]
public long[] BoundingBox { get; set; }
[JsonProperty("text")]
public string Text { get; set; }
[JsonProperty("words")]
public Word[] Words { get; set; }
}
public partial class Word
{
[JsonProperty("boundingBox")]
public long[] BoundingBox { get; set; }
[JsonProperty("text")]
public string Text { get; set; }
}
Then, deserialize the JSON to an instance of the Result class (let's call it result) using Newtonsoft.
And then you can
result.RecognitionResult.Where(s => !string.IsNullOrEmpty(s.Text) && s.Text == "lawyer");
If you just want the first occurance, use .FirstOrDefault()

JsonConvert.DeserializeObject Error reading object reference '1'

I am trying to deserialize an object in a Web Api from an object posted by angular. I am receiving an error: Error reading object reference '1'. Path 'Developers[0].DeveloperId', line 20, position 21
My Json object is (which has been validated as valid JSON):
{
"Id": 0,
"Name": "Name",
"OwnerId": 1,
"Description": "Description",
"Note": "My Notes",
"Stakeholders": [
{
"$id": "1",
"StakeholderId": 1,
"Name": "Mary",
"DateModified": "2018-02-21T12:28:15.023",
"DateCreated": "2018-02-21T12:28:15.023",
"$$hashKey": "object:3"
}
],
"Developers": [
{
"$id": "1",
"DeveloperId": 1,
"DeveloperName": "Joseph",
"DateModified": "2018-02-21T12:28:26.07",
"DateCreated": "2018-02-21T12:28:26.07",
"$$hashKey": "object:4"
}
]
}
I am trying to deserialize with:
var app = JsonConvert.DeserializeObject<Application>(request.ToString(), new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
The developer class (which is similar to Stakeholder class)
public class Developer : IModificationHistory
{
public int DeveloperId { get; set; }
[Required]
public string DeveloperName { get; set; }
[JsonIgnore]
public virtual List<Application> Applications { get; set; }
public DateTime DateModified { get; set; }
public DateTime DateCreated { get; set; }
}
The application class is simply:
public class Application
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
public string Note { get; set; }
public virtual List<Stakeholder> Stakeholders { get; set; }
public int OwnerId { get; set; }
public virtual List<Developer> Developers { get; set; }
}
The javascript I use to call this post is:
var data =
{
Id: vm.appId,
Name: vm.applicationName,
OwnerId: vm.owner.DeveloperId,
Description: vm.applicationDescription,
Note: vm.note,
Stakeholders: vm.selectedStakeholders,
Developers: vm.selectedDevelopers
};
$http.post("/api/Application/Post/", JSON.stringify(data))
The Stakeholders List gets filled properly, but the Developers list does not. If I put developers in the list before stakeholders, then developers list gets filled properly and stakeholders does not. Any suggestions would be greatly appreciated!
The problem is with the same value of $id, both are set to 1, see inner exception:
{"A different value already has the Id '1'."}
I just changed its value to 2 and it is working fine:
{
"Id": 0,
"Name": "Name",
"OwnerId": 1,
"Description": "Description",
"Note": "My Notes",
"Stakeholders": [
{
"$id": "1",
"StakeholderId": 1,
"Name": "Mary",
"DateModified": "2018-02-21T12:28:15.023",
"DateCreated": "2018-02-21T12:28:15.023",
"$$hashKey": "object:3"
}
],
"Developers": [
{
"$id": "2",
"DeveloperId": 1,
"DeveloperName": "Joseph",
"DateModified": "2018-02-21T12:28:26.07",
"DateCreated": "2018-02-21T12:28:26.07",
"$$hashKey": "object:4"
}
]
}
Here is the screenshot of my output:

Is this json format correct?

I have a json data when i'm trying to parse it returns error incorrect syntax please help me found the syntax error.
[{"isData":"Yes","Details":"[{"Id":"70","Name":"Test","FileName":"Uploaded","FileFormat":".mp4","FileType":"Video","FileDuration":"00:30:00 ","StartTime":"/Date(1372617000000)/","EndTime":"/Date(1372681771000)/","File":"2562013172331815635077778118152815.mp4"}]"}]
And this is the class that is used to serialize data, i am using javascript serializer
public enum Data
{
Yes,
No
}
public class MessageResponse()
{
public string isData { get; set; }
public string Details { get; set; }
}
List<MessageResponse> response = new List<MessageResponse>();
string strJson="[{"Id":"70","Name":"Test","FileName":"Uploaded","FileFormat":".mp4","FileType":"Video","FileDuration":"00:30:00 ","StartTime":"/Date(1372617000000)/","EndTime":"/Date(1372681771000)/","File":"2562013172331815635077778118152815.mp4"}]";
var newData = new MessageResponse
{
isData = Data.Yes.ToString(),
Details = strJson
};
response.Add(newData);
var jsonSerialiser1 = new JavaScriptSerializer();
string result = jsonSerialiser1.Serialize(response);
That's invalid JSON. The Details property is incorrectly formatted. You should remove the quotes around the value. It should be like this:
[
{
"isData": "Yes",
"Details": [
{
"Id": "70",
"Name": "Test",
"FileName": "Uploaded",
"FileFormat": ".mp4",
"FileType": "Video",
"FileDuration": "00:30:00 ",
"StartTime": "/Date(1372617000000)/",
"EndTime": "/Date(1372681771000)/",
"File": "2562013172331815635077778118152815.mp4"
}
]
}
]
or if you want Details to be a string property (representing JSON), which is kinda lame, you should properly escape the double quotes:
[
{
"isData": "Yes",
"Details": "[{\"Id\":\"70\",\"Name\":\"Test\",\"FileName\":\"Uploaded\",\"FileFormat\":\".mp4\",\"FileType\":\"Video\",\"FileDuration\":\"00: 30: 00\",\"StartTime\":\"/Date(1372617000000)/\",\"EndTime\":\"/Date(1372681771000)/\",\"File\":\"2562013172331815635077778118152815.mp4\"}]"
}
]
This structure you will be able to map to your current object model. But I would recommend you using the first approach.
Remove the " from the details data:
[{
"isData":"Yes",
"Details":
[{
"Id":"70",
"Name":"Test",
"FileName":"Uploaded",
"FileFormat":".mp4",
"FileType":"Video",
"FileDuration":"00:30:00",
"StartTime":"/Date(1372617000000)/",
"EndTime":"/Date(1372681771000)/",
"File":"2562013172331815635077778118152815.mp4"
}]
}]
Details should be of type class (i.e. user defined class) and it should hold all the properties.
public class Details
{ public int Id {get; set;} ... }
Firstly your json is invalid.
It should not have the " before and after the [ ]
[
{
"isData": "Yes",
"Details": [
{
"Id": "70",
"Name": "Test",
"FileName": "Uploaded",
"FileFormat": ".mp4",
"FileType": "Video",
"FileDuration": "00: 30: 00",
"StartTime": "/Date(1372617000000)/",
"EndTime": "/Date(1372681771000)/",
"File": "2562013172331815635077778118152815.mp4"
}
]
}
]
Secondly, your class could be improved to be:
public class MessageResponse
{
public string isData { get; set; }
public Details Details { get; set; }
}
public class Details
{
public int Id { get; set; }
public string Name { get; set; }
public string FileName { get; set; }
public string FileFormat { get; set; }
public string FileType { get; set; }
public string FileDuration { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
public string File { get; set; }
}
You would probably want to set up the correct data types though for things like Start Time etc...

Categories