Related
i have a Json file that contains some information i need elsewhere in my code but a lot of the information is irrelivant.
At the moment ive just put it into a dynamic object so i could check that it was all working:
var data = JsonConvert.DeserializeObject<dynamic>(response.Content);
How do i get the information i need out of the Json file and store them somewhere as variables.
All other tutorials where its stored in a class use the whole Json file and doesnt look like it would be useful in my case.
Here's the Json, i only really need the Stats section at the end of the file for what im doing
{
"data": {
"id": "",
"type": "player",
"children": [
{
"id": "legend_8",
"type": "legend",
"metadata": {
"legend_name": "Pathfinder",
"icon": "https://trackercdn.com/cdn/apex.tracker.gg/legends/pathfinder-tile.png",
"bgimage": "https://trackercdn.com/cdn/apex.tracker.gg/legends/pathfinder-concept-bg-small.jpg",
"is_active": true
},
"stats": [
{
"metadata": {
"key": "Kills",
"name": "Kills",
"categoryKey": "combat",
"categoryName": "Combat",
"isReversed": false
},
"value": 377.0,
"percentile": 21.0,
"displayValue": "377",
"displayRank": ""
},
{
"metadata": {
"key": "Finishers",
"name": "Finishers",
"categoryKey": "game",
"categoryName": "Game",
"isReversed": false
},
"value": 39.0,
"percentile": 0.2,
"rank": 886,
"displayValue": "39",
"displayRank": "886"
}
]
},
{
"id": "legend_5",
"type": "legend",
"metadata": {
"legend_name": "Bloodhound",
"icon": "https://trackercdn.com/cdn/apex.tracker.gg/legends/bloodhound-tile.png",
"bgimage": "https://trackercdn.com/cdn/apex.tracker.gg/legends/bloodhound-concept-bg-small.jpg",
"is_active": false
},
"stats": [
{
"metadata": {
"key": "Kills",
"name": "Kills",
"categoryKey": "combat",
"categoryName": "Combat",
"isReversed": false
},
"value": 235.0,
"percentile": 16.0,
"displayValue": "235",
"displayRank": ""
}
]
}
],
"metadata": {
"statsCategoryOrder": [
"combat",
"game",
"weapons"
],
"platformId": 2,
"platformUserHandle": "",
"accountId": "",
"cacheExpireDate": "11/10/2019 10:48:14 PM",
"level": 49,
"avatarUrl": "https://avatar-cdn.tracker.gg/api/avatar/2/",
"countryCode": null,
"collections": 36,
"activeLegend": 8
},
"stats": [
{
"metadata": {
"key": "Level",
"name": "Level",
"categoryKey": "combat",
"categoryName": "Combat",
"isReversed": false
},
"value": 49.0,
"percentile": 46.0,
"displayValue": "49",
"displayRank": ""
},
{
"metadata": {
"key": "Kills",
"name": "Kills",
"categoryKey": "combat",
"categoryName": "Combat",
"isReversed": false
},
"value": 612.0,
"percentile": 20.0,
"displayValue": "612",
"displayRank": ""
},
{
"metadata": {
"key": "Finishers",
"name": "Finishers",
"categoryKey": "game",
"categoryName": "Game",
"isReversed": false
},
"value": 39.0,
"percentile": 0.5,
"displayValue": "39",
"displayRank": ""
},
{
"metadata": {
"key": "RankScore",
"name": "Rank Score",
"categoryKey": "game",
"categoryName": "Game",
"isReversed": false
},
"value": 64.0,
"percentile": 21.0,
"displayValue": "64",
"displayRank": ""
}
]
}
}
You could create a data structure which has only the relevant properties. For example,
public class StatMetaData
{
public string key { get; set; }
public string name { get; set; }
public string categoryKey { get; set; }
public string categoryName { get; set; }
public bool isReversed { get; set; }
}
public class Stat
{
public StatMetaData metadata { get; set; }
public double value { get; set; }
public double percentile { get; set; }
public string displayValue { get; set; }
public string displayRank { get; set; }
}
public class Data
{
public List<Stat> stats { get; set; }
}
public class RootObject
{
public Data data { get; set; }
}
Now you could deserialize the json as the following to retrieve the stats sections
var result = JsonConvert.DeserializeObject<RootObject>(json).data.stats;
I am new to JSON and trying to develop a comparison table with data coming from 2 different JSON files as follows.
Json File 1
"data":[
{
"EffectiveDate": "2017-04-01T00:00:00Z",
"IncludedQuantity": 0,
"Category": "VM",
"Id": "d0bf9053",
"Name": "Element1",
"Rates": {
"0": 0.04
},
"Region": "US",
"Status": "Active",
"SubCategory": "S1",
"Tags": [],
"Unit": "Hours"
},
{
"EffectiveDate": "2017-02-01T00:00:00Z",
"IncludedQuantity": 0,
"Category": "DS",
"Id": "8b7672d4",
"Name": "Element2",
"Rates": {
"0": 4.0177
},
"Region": "UK",
"Status": "Active",
"SubCategory": "S2",
"Tags": [],
"Unit": "Days"
}]
Json File 2
"data":{
"d0bf9053":{
"EffectiveDate": "2017-04-01T00:00:00Z",
"IncludedQuantity": 0,
"Category": "VM",
"Id": "d0bf9053",
"Attributes":{
"Name": "Element1",
"Rates": {
"0": 5
},
"Region": "US",
"Status": "Active",
"SubCategory": "S1",
"Tags": [],
"Unit": "Hours"
}
},
"8b7672d4":{
"EffectiveDate": "2017-02-01T00:00:00Z",
"IncludedQuantity": 0,
"Category": "DS",
"Id": "8b7672d4",
"Attributes":{
"Name": "Element2",
"Rates": {
"0": 1
},
"Region": "UK",
"Status": "Active",
"SubCategory": "S2",
"Tags": [],
"Unit": "Days"
}
}}
Now I have to read this data and merge it to create a comparison based on rates and categories. I have created a Dot.Net Console Application and trying to use SQL Server to store the information. Now I am able to read JSON File 1 easily. But I am facing difficulty in storing values from JSON File 2. How do I solve this or am I wrong somewhere.
Thanks in advance.
The problem here is that you have dynamic property names in the second JSON file (Json File 2) and you are probably having trouble deserializing that JSON into a .Net Class, right?
Here are some examples that you can use to deserialize both Json1 and Json2 Types:
public class dataJson1
{
public List<Detail> data { get; set; }
}
public class dataJson2
{
public Dictionary<string, Detail> data { get; set; }
}
public class Detail
{
public DateTime EffectiveDate { get; set; }
public int IncludedQuantity { get; set; }
public string Category { get; set; }
//add the rest of the props here
}
That should get you started, once it's deserialized into those Objects, comparing them should be trivial.
i am having issue to get information from json response, i was trying to get information for label and value only from details object of json response, however i am unable to get those information because while converting json to c# classes from http://json2csharp.com/ gives different classes for 'General', 'AC Adapter' etc.. however in my case it will not work because the response having dynamic classes and therefore i cannot create classes.
{
"data": {
"General": {
"label": "General",
"details": [
{
"label": "Operating System",
"value": "Google Chrome OS"
},
{
"label": "Product Type",
"value": "Chromebook"
}
]
},
"AC Adapter": {
"label": "AC Adapter",
"details": [
{
"label": "Input",
"value": "AC 120/230 V ( 50/60 Hz )"
},
{
"label": "Output",
"value": "45 Watt , 20 V , 2.25 A"
}
]
},
"Audio & Video": {
"label": "Audio & Video",
"details": [
{
"label": "Camera",
"value": "Yes - 720p"
},
{
"label": "Graphics Processor",
"value": "Intel HD Graphics"
},
{
"label": "Resolution",
"value": "1 Megapixel"
},
{
"label": "Sound",
"value": "Stereo speakers , microphone"
}
]
},
"Battery": {
"label": "Battery",
"details": [
{
"label": "Capacity",
"value": "45 Wh"
},
{
"label": "Run Time",
"value": "Up to 10 hours"
},
{
"label": "Technology",
"value": "3-cell lithium ion"
}
]
},
"Communications": {
"label": "Communications",
"details": [
{
"label": "Features",
"value": "Dual stream (2x2)"
},
{
"label": "Wireless",
"value": "Bluetooth 4.0, 802.11a/b/g/n/ac"
},
{
"label": "Wireless Controller",
"value": "Intel Dual Band Wireless-AC 7260 - M.2 Card"
}
]
},
"Connections & Expansion": {
"label": "Connections & Expansion",
"details": [
{
"label": "Interfaces",
"value": "USB 3.0 � 2 x USB 2.0 � HDMI � Headphone/microphone combo jack"
},
{
"label": "Memory Card Reader",
"value": "Yes ( microSD )"
}
]
},
"Dimensions & Weight": {
"label": "Dimensions & Weight",
"details": [
{
"label": "Dimensions (WxDxH)",
"value": "11.8 in x 8.5 in x 0.9 in"
},
{
"label": "Weight",
"value": "2.84 lbs"
}
]
},
"Display": {
"label": "Display",
"details": [
{
"label": "Features",
"value": "Anti-glare"
},
{
"label": "Image Aspect Ratio",
"value": "16:9"
},
{
"label": "LCD Backlight Technology",
"value": "LED backlight"
},
{
"label": "Resolution",
"value": "1366 x 768 ( HD )"
},
{
"label": "Type",
"value": "11.6\""
},
{
"label": "Widescreen",
"value": "Yes"
}
]
},
"Input": {
"label": "Input",
"details": [
{
"label": "Features",
"value": "Spill-resistant"
},
{
"label": "Type",
"value": "Keyboard, touchpad"
}
]
},
"Manufacturer Warranty": {
"label": "Manufacturer Warranty",
"details": [
{
"label": "Service & Support",
"value": "Limited warranty - 1 year - carry-in"
}
]
},
"Memory": {
"label": "Memory",
"details": [
{
"label": "Max RAM Supported",
"value": "8 GB"
},
{
"label": "RAM",
"value": "4 GB ( provided memory is soldered )"
},
{
"label": "Speed",
"value": "1600 MHz"
},
{
"label": "Technology",
"value": "DDR3L SDRAM"
}
]
},
"Miscellaneous": {
"label": "Miscellaneous",
"details": [
{
"label": "Features",
"value": "Security lock slot (cable lock sold separately), administrator password, hard drive password, power-on password"
},
{
"label": "Included Accessories",
"value": "Power adapter"
},
{
"label": "Localization",
"value": "English"
},
{
"label": "Manufacturer Selling Program",
"value": "TopSeller"
}
]
},
"Processor / Chipset": {
"label": "Processor / Chipset",
"details": [
{
"label": "64-bit Computing",
"value": "Yes"
},
{
"label": "CPU",
"value": "Intel Celeron N3050 / 1.6 GHz"
},
{
"label": "Cache",
"value": "2 MB"
},
{
"label": "Features",
"value": "Integrated memory controller"
},
{
"label": "Max Turbo Speed",
"value": "2.16 GHz"
},
{
"label": "Number of Cores",
"value": "Dual-Core"
}
]
},
"Storage": {
"label": "Storage",
"details": [
{
"label": "Main Storage",
"value": "16 GB SSD - ( eMMC )"
}
]
}
}
}
http://json2csharp.com/ gives different classes for 'General', 'AC Adapter' etc
This works better: https://quicktype.io/?l=cs&r=json2csharp
However, I think your data is actually a dictionary here. So the final contract:
public class Response
{
[JsonProperty("data")]
public Data Data { get; set; }
}
public class Data : Dictionary<string, Item> { }
public class Item
{
[JsonProperty("details")]
public Detail[] Details { get; set; }
[JsonProperty("label")]
public string Label { get; set; }
}
public class Detail
{
[JsonProperty("label")]
public string Label { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
}
And if you use Newtonsoft, deserialization:
var response = JsonConvert.DeserializeObject<Response>(jsonString);
if you just want to convert a json string to C# dynamic object, look at this SO question. The code is in the final version.
Greeting,
I am finding difficulty in parsing a JSON format file in c# having an array of highly nested objects which looks as follows
[
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
},
{
"id": "0002",
"type": "donut",
"name": "Raised",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
},
{
"id": "0003",
"type": "donut",
"name": "Old Fashioned",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}
]
I am looking for a solution like
"id", "type","name", "ppu" as private members of a class and "batters" and "topping" as dictionary members.
Kindly suggest me the better way in getting it parsed.
Thank you.
Following class structure will help you to parse JSON to C# object.
public class Batter
{
public string id { get; set; }
public string type { get; set; }
}
public class Batters
{
public List<Batter> batter { get; set; }
}
public class Topping
{
public string id { get; set; }
public string type { get; set; }
}
public class RootObject
{
public string id { get; set; }
public string type { get; set; }
public string name { get; set; }
public double ppu { get; set; }
public Batters batters { get; set; }
public List<Topping> topping { get; set; }
}
I need to deserialize the this json returned from grogle maps api:
{
"destination_addresses": [
"Via Medaglie D'Oro, 10, 47121 Forlì FC, Italia",
"Via Torino, 20123 Milano, Italia",
"Via Guglielmo Marconi, 71, 40121 Bologna, Italia",
"Via Irnerio, 40126 Bologna, Italia"
],
"origin_addresses": [
"Via Medaglie D'Oro, 10, 47121 Forlì FC, Italia",
"Via Torino, 20123 Milano, Italia",
"Via Guglielmo Marconi, 71, 40121 Bologna, Italia",
"Via Irnerio, 40126 Bologna, Italia"
],
"rows": [
{
"elements": [
{
"distance": {
"text": "1 m",
"value": 0
},
"duration": {
"text": "1 min",
"value": 0
},
"status": "OK"
},
{
"distance": {
"text": "286 km",
"value": 286281
},
"duration": {
"text": "2 ore 48 min",
"value": 10083
},
"status": "OK"
},
{
"distance": {
"text": "80,1 km",
"value": 80088
},
"duration": {
"text": "1 ora 3 min",
"value": 3789
},
"status": "OK"
},
{
"distance": {
"text": "77,6 km",
"value": 77594
},
"duration": {
"text": "57 min",
"value": 3422
},
"status": "OK"
}
]
},
{
"elements": [
{
"distance": {
"text": "288 km",
"value": 287811
},
"duration": {
"text": "2 ore 48 min",
"value": 10052
},
"status": "OK"
},
{
"distance": {
"text": "1 m",
"value": 0
},
"duration": {
"text": "1 min",
"value": 0
},
"status": "OK"
},
{
"distance": {
"text": "212 km",
"value": 212423
},
"duration": {
"text": "2 ore 8 min",
"value": 7664
},
"status": "OK"
},
{
"distance": {
"text": "218 km",
"value": 218219
},
"duration": {
"text": "2 ore 9 min",
"value": 7740
},
"status": "OK"
}
]
},
{
"elements": [
{
"distance": {
"text": "78,5 km",
"value": 78528
},
"duration": {
"text": "56 min",
"value": 3346
},
"status": "OK"
},
{
"distance": {
"text": "212 km",
"value": 212190
},
"duration": {
"text": "2 ore 5 min",
"value": 7519
},
"status": "OK"
},
{
"distance": {
"text": "1 m",
"value": 0
},
"duration": {
"text": "1 min",
"value": 0
},
"status": "OK"
},
{
"distance": {
"text": "2,0 km",
"value": 1979
},
"duration": {
"text": "5 min",
"value": 316
},
"status": "OK"
}
]
},
{
"elements": [
{
"distance": {
"text": "74,7 km",
"value": 74719
},
"duration": {
"text": "55 min",
"value": 3278
},
"status": "OK"
},
{
"distance": {
"text": "218 km",
"value": 217951
},
"duration": {
"text": "2 ore 9 min",
"value": 7712
},
"status": "OK"
},
{
"distance": {
"text": "3,8 km",
"value": 3782
},
"duration": {
"text": "11 min",
"value": 671
},
"status": "OK"
},
{
"distance": {
"text": "1 m",
"value": 0
},
"duration": {
"text": "1 min",
"value": 0
},
"status": "OK"
}
]
}
],
"status": "OK"
}
I need to create a Distance Matrix so I'm only interested in the "value" field inside "distance".
I've tried this approach:
DataSet data = JsonConvert.DeserializeObject<DataSet>(jsonResponse);
DataTable dataTab = data.Tables["Elements"];
foreach (DataRow elements in dataTab.Rows)
{
Console.WriteLine(elements["distance"]);
//Do something else here
}
But The JSonConvert returns "Additional text found in JSON string after finishing deserializing object."
You should deserialize to classes that match your data. You can generate these classes at http://json2csharp.com/.
// use like
var rootObj = JsonConvert.DeserializeObject<RootObject>(jsonResponse);
foreach (var row in rootObj.rows)
{
foreach (var element in row.elements)
{
Console.WriteLine(element.distance.text);
}
}
// you might want to change the property names to .Net conventions
// use [JsonProperty] to let the serializer know the JSON names where needed
public class Distance
{
public string text { get; set; }
public int value { get; set; }
}
public class Duration
{
public string text { get; set; }
public int value { get; set; }
}
public class Element
{
public Distance distance { get; set; }
public Duration duration { get; set; }
public string status { get; set; }
}
public class Row
{
public List<Element> elements { get; set; }
}
public class RootObject
{
public List<string> destination_addresses { get; set; }
public List<string> origin_addresses { get; set; }
public List<Row> rows { get; set; }
public string status { get; set; }
}
I believe the issue is with the cast to 'DataSet' based on a similar question I found searching Stack Overflow.
Try this as I believe it would work (you may need to use 'rows' instead of 'Elements', but I believe the approach of using a JObject will resolve the primary issue of the 'additional text'.
JObject json = JsonConvert.DeserializeObject<JObject>(jsonResponse);
foreach (Dictionary<string, object> item in data["Elements"])
{
foreach (string val in item.Values) {
Console.WriteLine(val);
}
}
Using dynamic :
dynamic json = JsonConvert.DeserializeObject(jsonResponse);
var rowCount = json.rows.Count;
Func<dynamic, int> getElementCount = r => r.elements.Count;
var maxElements = Enumerable.Max(json.rows, getElementCount);
var matrix = new int?[rowCount, maxElements];
for(int i = 0; i < rowCount; i++)
{
var elements = json.rows[i].elements;
for(int j = 0; j < elements.Count; j++)
{
var element = elements[j];
matrix[i, j] = element.distance.value;
}
}