4

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 brain dead.

I have this json data (apologies for length) and am trying, as a start to get the 'value' number in the 'Values' array:-

{
  "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"
        }
      ]
    }
  ]
}

I have created classes using http://json2csharp.com/ and have tried methods such as:-

RootObject ro = JsonConvert.DeserializeObject<RootObject>(json_data);

and

Value [] vo = JsonConvert.DeserializeObject<Value[]>(json_data);

and

dynamic result = JsonConvert.DeserializeObject(json_data);

also

JavaScriptSerializer jss = new JavaScriptSerializer();
Value [] thisval = jss.Deserialize<Value[]>(json_data);

Among others. What would be the correct way to extract his information into the classes so then i could work on them. An example of calling the data once deserialized would be helpful. The main classes I have are

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; }
}
1
  • Well RootObject ro = JsonConvert.DeserializeObject<RootObject>(json_data); works for me (using blank classes for Metadata and Column) Commented Nov 25, 2014 at 17:29

2 Answers 2

5

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:

deserialize complex json to c# class

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, Values 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

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the clear answer with working example. Just one further question. With the List within a List, how would I reference just one value eg var test = rootObject.rows[0].values[1].value
Yes, that is correct. You would use rows[0].values[1].value to access the 1st item in the rows list (indexer starts at 0) and the 2nd Value item in the values list inside the rows list. I have updated the fiddle linked in my answer to print this out too, so check that out!
2

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; }
}

1 Comment

Thanks for the answer, I think I will definitely need this for further programming.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.