I have been trying to deserialize the following json data into classes for 2 days using the help from similar questions on this and other sites, and might possibly be going
Use a json to C# generator like JSON C# Class Generator.
You can replace the arrays with Lists and drop the JsonProperty
attributes if you rename the properties and make them match the json's name.
Here's the output:
internal class Test
{
[JsonProperty("metadata")]
public Metadata Metadata { get; set; }
[JsonProperty("columns")]
public Column[] Columns { get; set; }
[JsonProperty("rows")]
public Row[] Rows { get; set; }
}
internal class Metadata
{
[JsonProperty("columnGrouping")]
public string[] ColumnGrouping { get; set; }
[JsonProperty("rowGrouping")]
public object[] RowGrouping { get; set; }
}
internal class Area
{
[JsonProperty("identifier")]
public string Identifier { get; set; }
[JsonProperty("label")]
public string Label { get; set; }
[JsonProperty("altLabel")]
public string AltLabel { get; set; }
[JsonProperty("isSummary")]
public bool IsSummary { get; set; }
}
internal class MetricType
{
[JsonProperty("identifier")]
public string Identifier { get; set; }
[JsonProperty("label")]
public string Label { get; set; }
[JsonProperty("altLabel")]
public string AltLabel { get; set; }
[JsonProperty("isSummary")]
public bool IsSummary { get; set; }
}
internal class Period
{
[JsonProperty("identifier")]
public string Identifier { get; set; }
[JsonProperty("label")]
public string Label { get; set; }
[JsonProperty("altLabel")]
public string AltLabel { get; set; }
[JsonProperty("isSummary")]
public bool IsSummary { get; set; }
}
internal class ValueType
{
[JsonProperty("identifier")]
public string Identifier { get; set; }
[JsonProperty("label")]
public string Label { get; set; }
[JsonProperty("isSummary")]
public bool IsSummary { get; set; }
}
internal class Column
{
[JsonProperty("area")]
public Area Area { get; set; }
[JsonProperty("metricType")]
public MetricType MetricType { get; set; }
[JsonProperty("period")]
public Period Period { get; set; }
[JsonProperty("valueType")]
public ValueType ValueType { get; set; }
}
internal class Value
{
[JsonProperty("source")]
public double Source { get; set; }
[JsonProperty("value")]
public double Value { get; set; }
[JsonProperty("formatted")]
public string Formatted { get; set; }
[JsonProperty("format")]
public string Format { get; set; }
[JsonProperty("publicationStatus")]
public string PublicationStatus { get; set; }
}
internal class Row
{
[JsonProperty("values")]
public Value[] Values { get; set; }
}
Here's a working dotNet Fiddle that deserializes the Values
List. https://dotnetfiddle.net/7P2em6
Wait few seconds when you load the fiddle and notice the output in the Console window. The code should be self-explanatory, but let me know if you need help.
I have also pasted it below for completeness in case dotNetFiddle is not available.
Console Output:
I used http://json2csharp.com/ to generate the classes from the JSON string.
I think your issue might have been that Values
is a List
inside the Row
object, which, in turn, is a List
inside the RootObject
. In other words, Value
s are stored as a List
inside a List
.
Complete Code Listing
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Runtime.Serialization;
using System.Web;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
// SO Question: http://stackoverflow.com/questions/27132887/
// This (my) Answer:
// Author: Shiva Manjunath
// SO Profile: http://stackoverflow.com/users/325521/shiva
public class Program
{
public static void Main()
{
string jsonString = @"{
""metadata"": {
""columnGrouping"": [
""area"",
""metricType"",
""period"",
""valueType""
],
""rowGrouping"": []
},
""columns"": [
{
""area"": {
""identifier"": ""E31000040"",
""label"": ""Gtr Manchester Fire"",
""altLabel"": ""Gtr Manchester Fire"",
""isSummary"": false
},
""metricType"": {
""identifier"": ""948"",
""label"": ""Accidental dwelling fires"",
""altLabel"": ""Accidental dwelling fires"",
""isSummary"": false
},
""period"": {
""identifier"": ""fq_Q1_2013_14"",
""label"": ""2013/14 Q1"",
""altLabel"": ""2013/14 Q1"",
""isSummary"": false
},
""valueType"": {
""identifier"": ""raw"",
""label"": ""Raw value"",
""isSummary"": false
}
},
{
""area"": {
""identifier"": ""E31000040"",
""label"": ""Gtr Manchester Fire"",
""altLabel"": ""Gtr Manchester Fire"",
""isSummary"": false
},
""metricType"": {
""identifier"": ""948"",
""label"": ""Accidental dwelling fires"",
""altLabel"": ""Accidental dwelling fires"",
""isSummary"": false
},
""period"": {
""identifier"": ""fq_Q2_2013_14"",
""label"": ""2013/14 Q2"",
""altLabel"": ""2013/14 Q2"",
""isSummary"": false
},
""valueType"": {
""identifier"": ""raw"",
""label"": ""Raw value"",
""isSummary"": false
}
},
{
""area"": {
""identifier"": ""E31000040"",
""label"": ""Gtr Manchester Fire"",
""altLabel"": ""Gtr Manchester Fire"",
""isSummary"": false
},
""metricType"": {
""identifier"": ""948"",
""label"": ""Accidental dwelling fires"",
""altLabel"": ""Accidental dwelling fires"",
""isSummary"": false
},
""period"": {
""identifier"": ""fq_Q3_2013_14"",
""label"": ""2013/14 Q3"",
""altLabel"": ""2013/14 Q3"",
""isSummary"": false
},
""valueType"": {
""identifier"": ""raw"",
""label"": ""Raw value"",
""isSummary"": false
}
},
{
""area"": {
""identifier"": ""E31000040"",
""label"": ""Gtr Manchester Fire"",
""altLabel"": ""Gtr Manchester Fire"",
""isSummary"": false
},
""metricType"": {
""identifier"": ""948"",
""label"": ""Accidental dwelling fires"",
""altLabel"": ""Accidental dwelling fires"",
""isSummary"": false
},
""period"": {
""identifier"": ""fq_Q4_2013_14"",
""label"": ""2013/14 Q4"",
""altLabel"": ""2013/14 Q4"",
""isSummary"": false
},
""valueType"": {
""identifier"": ""raw"",
""label"": ""Raw value"",
""isSummary"": false
}
}
],
""rows"": [
{
""values"": [
{
""source"": 515.0,
""value"": 515.0,
""formatted"": ""515"",
""format"": ""#,##0"",
""publicationStatus"": ""Published""
},
{
""source"": 264.0,
""value"": 264.0,
""formatted"": ""264"",
""format"": ""#,##0"",
""publicationStatus"": ""Published""
},
{
""source"": 254.0,
""value"": 254.0,
""formatted"": ""254"",
""format"": ""#,##0"",
""publicationStatus"": ""Published""
},
{
""source"": 455.0,
""value"": 455.0,
""formatted"": ""455"",
""format"": ""#,##0"",
""publicationStatus"": ""Published""
}
]
}
]
}";
Console.WriteLine("Begin JSON Deserialization\n");
var rootObject = JsonConvert.DeserializeObject<RootObject>(jsonString);
var rows = rootObject.rows;
int rowCounter = 1;
foreach (Row oneRow in rows)
{
Console.WriteLine("Row: " + rowCounter);
int valueCounter = 1;
foreach(Value oneValue in oneRow.values)
{
Console.WriteLine(" Value: " + valueCounter);
Console.WriteLine(" source: " + oneValue.source);
Console.WriteLine(" value: " + oneValue.value);
Console.WriteLine(" formatted: " + oneValue.formatted);
Console.WriteLine(" publicationStatus: " + oneValue.publicationStatus);
valueCounter++;
}
rowCounter++;
}
Console.WriteLine("\nEnd JSON Deserialization");
}
}
public class Metadata
{
public List<string> columnGrouping { get; set; }
}
public class Area
{
public string identifier { get; set; }
public string label { get; set; }
public string altLabel { get; set; }
public bool isSummary { get; set; }
}
public class MetricType
{
public string identifier { get; set; }
public string label { get; set; }
public string altLabel { get; set; }
public bool isSummary { get; set; }
}
public class Period
{
public string identifier { get; set; }
public string label { get; set; }
public string altLabel { get; set; }
public bool isSummary { get; set; }
}
public class ValueType
{
public string identifier { get; set; }
public string label { get; set; }
public bool isSummary { get; set; }
}
public class Column
{
public Area area { get; set; }
public MetricType metricType { get; set; }
public Period period { get; set; }
public ValueType valueType { get; set; }
}
public class Value
{
public double source { get; set; }
public double value { get; set; }
public string formatted { get; set; }
public string format { get; set; }
public string publicationStatus { get; set; }
}
public class Row
{
public List<Value> values { get; set; }
}
public class RootObject
{
public Metadata metadata { get; set; }
public List<Column> columns { get; set; }
public List<Row> rows { get; set; }
}
NOTE: For the columns
object, you don't need separate classes for the fields (json2csharp.com class generator will default to that). You can store the values in the columns
object in a dictionary class (if you know that their names will be unique). For an implementation of that (different JSON string, but same json schema type, principle) see this fiddle: https://dotnetfiddle.net/7bFcNM