Json.NET: deserialize json arrays

I am trying to process a JSON structure using Json.NET and have encountered some problems:

My classes do not work when JSON contains an unnamed array.

Json Example:

{ "graph_property" : [{ "name" : "calculation_method", "value" : "Arithmetic" }, { "name" : "graph_type", "value" : "TIME" } ], "measurement" : [{ "id" : "9997666", "alias" : "Measurement (TxP)[IE]-Home Page - Total Time (seconds)", "bucket_data" : [{ "name" : "2013-MAR-18 12:00 AM", "id" : 1, "perf_data" : { "value" : "2.244", "unit" : "seconds" }, "avail_data" : { "value" : "99.67", "unit" : "percent" }, "data_count" : { "value" : "299", "unit" : "#" } } ], "graph_option" : [{ "name" : "perfwarning", "value" : "-", "unit" : "seconds" }, { "name" : "perfcritical", "value" : "-", "unit" : "seconds" }, { "name" : "availwarning", "value" : "-", "unit" : "percent" }, { "name" : "availcritical", "value" : "-", "unit" : "percent" }, { "name" : "bucketsize", "value" : "86400", "unit" : "seconds" }, { "name" : "rows", "value" : "1", "unit" : "#" }, { "name" : "pagecomponent", "value" : "Total Time", "unit" : "seconds" }, { "name" : "avg_perf", "value" : "2.244", "unit" : "seconds" }, { "name" : "avg_avail", "value" : "99.67", "unit" : "percent" }, { "name" : "total_datapoint_count", "value" : "300", "unit" : "#" }, {} ] }, { "id" : "9997666", "alias" : "Measurement (TxP)[IE]-Women - Total Time (seconds)", "bucket_data" : [{ "name" : "2013-MAR-18 12:00 AM", "id" : 1, "perf_data" : { "value" : "0.979", "unit" : "seconds" }, "avail_data" : { "value" : "100.00", "unit" : "percent" }, "data_count" : { "value" : "299", "unit" : "#" } } ], "graph_option" : [{ "name" : "perfwarning", "value" : "-", "unit" : "seconds" }, { "name" : "perfcritical", "value" : "-", "unit" : "seconds" }, { "name" : "availwarning", "value" : "-", "unit" : "percent" }, { "name" : "availcritical", "value" : "-", "unit" : "percent" }, { "name" : "bucketsize", "value" : "86400", "unit" : "seconds" }, { "name" : "rows", "value" : "1", "unit" : "#" }, { "name" : "pagecomponent", "value" : "Total Time", "unit" : "seconds" }, { "name" : "avg_perf", "value" : "0.979", "unit" : "seconds" }, { "name" : "avg_avail", "value" : "100.00", "unit" : "percent" }, { "name" : "total_datapoint_count", "value" : "299", "unit" : "#" }, {} ] } ], "link" : { "type" : "application/json", "href" : "http://api.website.tld?format=json", "rel" : "slotmetadata" } } 

Class for Json.NET:

 using System; using System.Collections.Generic; namespace CAKR.Graph { /// <summary> /// Description of KN_Graph. /// </summary> public class GraphProperty { public string name { get; set; } public string value { get; set; } } public class PerfData { public string value { get; set; } public string unit { get; set; } } public class AvailData { public string value { get; set; } public string unit { get; set; } } public class DataCount { public string value { get; set; } public string unit { get; set; } } public class BucketData { public string name { get; set; } public int id { get; set; } public PerfData perf_data { get; set; } public AvailData avail_data { get; set; } public DataCount data_count { get; set; } } public class GraphOption { public string name { get; set; } public string value { get; set; } public string unit { get; set; } } public class Measurement { public string id { get; set; } public string alias { get; set; } public List<BucketData> bucket_data { get; set; } public List<GraphOption> graph_option { get; set; } } public class Link { public string type { get; set; } public string href { get; set; } public string rel { get; set; } } public class RootObject { public List<GraphProperty> graph_property { get; set; } public List<Measurement> measurement { get; set; } public Link link { get; set; } } } 

My code is:

 var myObject = JsonConvert.DeserializeObject<CAKR.Graph.Measurement>(MyJsonString); 

I am not sure why I am not getting an object containing the data of the child dimension array. If I insert named values, it works ...

+6
source share
4 answers

So for a long time I fought for this to work. However, in the end, the decision is not so difficult. I hope that with my answer I will help some people.

The solution in my case was

  • Install JSON.net in your project using nu.get
  • Make your JSON object, including an array, in an array, etc. Make sure the format of the object is correct! Example...

{"ProductDetail": [

  { "ProjectImg" : "http://placehold.it/400x300", "Category" : "Cars", "ProjectTitle" : "Cars of the future", "ProjectDesc" : "Test project", "GenSpecList" : ["Specs1", "Specs2", "Specs3", "Specs4"], "OptionList" : [{ "OptionNr" : "1", "Options" : ["Opt1", "Opt2", "Opt3"] }, { "OptionNr" : "2", "Options" : ["Opt1", "Opt2", "Opt3"] }, { "OptionNr" : "3", "Options" : ["Opt1", "Opt2", "Opt3"] }, { "OptionNr" : "4", "Options" : ["Opt1", "Opt2", "Opt3"] }, { "OptionNr" : "5", "Options" : ["Opt1", "Opt2", "Opt3"] }, { "OptionNr" : "6", "Options" : ["Opt1", "Opt2", "Opt3"] } ], "Articles" : [{ "tileImg" : "'Images/Project/1.jpg'", "tileTit" : "Title1", "tileArt" : "Article text here..." }, { "tileImg" : "'Images/Project/2.jpg'", "tileTit" : "Title2", "tileArt" : "Article text here..." }, { "tileImg" : "'Images/Project/3.jpg'", "tileTit" : "Title3", "tileArt" : "Article text here..." }, { "tileImg" : "'Images/Project/4.jpg'", "tileTit" : "Title4", "tileArt" : "Article text here..." } ] } ] } 
  • Go to json2csharp.com and copy the JSON object into the input field and click the generate button. Copy the csharp model (this is actually the key to solving my fight!) Generated in your ViewModel.
  • In my case, the main class of all generated json2csharp.com classes was RootObject and looked below

     public class Article { public string tileImg { get; set; } public string tileTit { get; set; } public string tileArt { get; set; } } public class OptionList { public string OptionNr { get; set; } public List<string> Options { get; set; } } public class ProductDetail { public string ProjectImg { get; set; } public string Category { get; set; } public string ProjectTitle { get; set; } public string ProjectDesc { get; set; } public List<string> GenSpecList { get; set; } public List<OptionList> OptionList { get; set; } public List<Article> Articles { get; set; } } public class RootObject { public List<ProductDetail> ProductDetail { get; set; } } 
  • Then use the following code in the controller (just copy the full file here)

     using Project.Details; //<-- this is my ViewModel namespace name using Newtonsoft.Json; using System.IO; using System.Threading.Tasks; namespace WebApplication.Controllers { public class JSONController : Controller { // // GET: /JSON/ public async Task<ActionResult> Index() { StreamReader file = new StreamReader("C:\\Users\\YourName\\etc\\File.json"); String json = await file.ReadToEndAsync(); var Project = JsonConvert.DeserializeObject<RootObject>(json); return View(); } } } 

Now everything should work fine, array in array, etc. I hope you found my solution useful, please note that I am not dying as a programmer, so if I miss everything in terms of efficiency, I hope to get some tips from you to improve this code ...

Regards, Raymond

+8
source

You are almost there. Just use

 var myObject = JsonConvert.DeserializeObject<CAKR.Graph.RootObject>(MyJsonString); 

instead

 var myObject = JsonConvert.DeserializeObject<CAKR.Graph.Measurement>(MyJsonString); 
+4
source

First of all, you do not need to name all the properties of your Measurement class exactly as they appear in MyJsonString . You can use the JsonProperty attribute and decorate your class properties.

Another thing is if you want to deserialize part of your MyJsonString and extract only the array from Measurement , you must specify the correct type T for the Deserialize method (in your case, this is IEnumerable<Measurement> .

The following code should help:

  dynamic context = JObject.Parse(MyJsonString); var myObject = JsonConvert.DeserializeObject<IEnumerable<Measurement>>(context.measurement.ToString()); 
+2
source

I use a very simple method to deserialize Json arrays. Instead of using tons of public classes with numerous public variables. I just use a dynamic object and pass json as a JSONConvert.DeserializeObject object.

Here's how it will work. Let's say I have the following JSON:

 string json = { 'Name': 'John Doe', 'Address': { 'City': 'Atlanta', 'State': 'GA' }, 'Age': 30} 

I can pass a json string to a JSONConvert.DeserializeObject object.

 dynamic outputArray = JsonConvert.DeserializeObject(json); 

Then, using the newly created dynamic element, I can collect Json data like this.

 string getName = outputArray.Name //This will return "John Doe" 

If you have an array inside your Json, you can use

 string getCity = outputArray.Address.City; //This will return "Atlanta". 

It's very easy to change where you retrieve data from without having a cluster of public variables ... You can save the values ​​in public variables if you want.

The following describes how I use the full method:

 using (var client = new WebClient()) { string json = client.DownloadString(url); string output = json.ToString(); dynamic outputArray = JsonConvert.DeserializeObject(output); string _age = outputArray.age; string appID = outputArray.data.app_id; Debug.Write(outputArray.Something); //Just match value of json } 
0
source

All Articles