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

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()

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'

JSON Array without array name into property

I have a problem deserializing JSON responses from the RIOT API in C#. I want to get a list of LeagueEntryDTO.
The API return a stream looks like this :
[
{
"leagueId": "c83a16ca-b80e-4456-9f57-bc0f2a6020ae",
"queueType": "RANKED_SOLO_5x5",
"tier": "DIAMOND",
"rank": "II",
"summonerId": "XrhB60yIVT_t6Uwp0XuWRpFYD49_Ypk9ycybSdt6LS9Lv5E",
"summonerName": "MasterPrzecin",
"leaguePoints": 7,
"wins": 68,
"losses": 62,
"veteran": false,
"inactive": false,
"freshBlood": false,
"hotStreak": false},
{
"leagueId": "6b3e4e2e-cc90-4e06-afb2-7c2f4b0be9ab",
"queueType": "RANKED_FLEX_SR",
"tier": "PLATINUM",
"rank": "III",
"summonerId": "XrhB60yIVT_t6Uwp0XuWRpFYD49_Ypk9ycybSdt6LS9Lv5E",
"summonerName": "MasterPrzecin",
"leaguePoints": 58,
"wins": 7,
"losses": 7,
"veteran": false,
"inactive": false,
"freshBlood": false,
"hotStreak": false
}
]
This is my current code to transform the data which is failing:
public class LeagueEntryDTOService : ILeagueEntryDTOService
{
RestClient client = new RestClient("https://eun1.api.riotgames.com/lol/league/v4/entries/");
public LeagueEntryDTOResponse GetLeagueEntryDTO()
{
var request = new RestRequest("by-summoner/{encryptedSummonerId}")
.AddParameter("encryptedSummonerId", "XrhB60yIVT_t6Uwp0XuWRpFYD49_Ypk9ycybSdt6LS9Lv5E", ParameterType.UrlSegment)
.AddParameter("api_key", "key");
var response = client.Execute<LeagueEntryDTOResponse>(request);
if (!response.IsSuccessful)
{
return null;
}
return response.Data;
}
public class LeagueEntryDTOResponse
{
public ICollection<AllRanks> Ranks { get; set; }
}
public class AllRanks
{
public string Tier { get; set; }
public string Rank { get; set; }
public int LeaguePoints { get; set; }
public int Wins { get; set; }
public int Losses { get; set; }
}
}
}
What is a good way to deserialize this data?
You have a list of AllRanks instead of an object that contains a list of AllRanks. If there was a property name before the list array, then you would go about deserializing the json off of LeagueEntryDTOResponse but in this case, List<AllRanks> will do
Try this,
client.Execute<List<AllRanks>>(request)
Also, your class attributes must match the case of the json properties. You can either match the case when declaring the variables or you can add [JsonProperty()] to define the exact match. Since convention is to use first letter as UpperCase, its best to define the JsonProperties like below.
public class AllRanks
{
[JsonProperty("tier")]
public string Tier { get; set; }
[JsonProperty("rank")]
public string Rank { get; set; }
[JsonProperty("leaguePoints")]
public int LeaguePoints { get; set; }
[JsonProperty("wins")]
public int Wins { get; set; }
[JsonProperty("losses")]
public int Losses { get; set; }
}
Since you are returning List<AllRanks>, you will need to change the return type of the method as well,
public List<AllRanks> GetLeagueEntryDTO()

Deserialize Complex JSON

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.

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.

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