将复杂的JSON转换为C#类

4

我已经尝试了两天,借助于其他网站上类似问题的帮助,将以下json数据反序列化为类,并可能会变得脑残。

我有这个json数据(长度很长,抱歉),并且正在尝试从'Values'数组中获取'value'数字:

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

我使用http://json2csharp.com/创建了类,并尝试了以下方法:

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

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

并且

dynamic result = JsonConvert.DeserializeObject(json_data);

also

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

除此之外,正确的方法是将其信息提取到类中,这样我就可以对它们进行操作。一旦反序列化,调用数据的示例将会很有帮助。 我主要拥有的类是:

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

对我来说,RootObject ro = JsonConvert.DeserializeObject<RootObject>(json_data);是可行的(使用空的 MetadataColumn 类)。 - DavidG
2个回答

5

这是一个可以工作的dotNet Fiddle,可以反序列化Values列表。https://dotnetfiddle.net/7P2em6

加载Fiddle时,请等待几秒钟,并注意控制台窗口中的输出。代码应该是自我解释的,但如果需要帮助,请告诉我。

为了完整起见,我还将其粘贴在下面,以防dotNetFiddle不可用。

控制台输出:

deserialize complex json to c# class

我使用 http://json2csharp.com/ 来从JSON字符串生成类。

我认为您的问题可能是ValuesRow对象内部的List,而Row对象又是RootObject内部的List。换句话说,Value被存储为List内部的List

完整代码清单

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: https://dev59.com/goXca4cB1Zd3GeqPJIGl
    // 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; }
}

注意: 对于columns对象,您不需要为字段创建单独的类(json2csharp.com类生成器将默认使用该方法)。如果您知道它们的名称是唯一的,则可以将值存储在一个字典类的columns对象中。有关其实现的示例(不同的JSON字符串,但相同的JSON schema类型原理),请参见此fiddle: https://dotnetfiddle.net/7bFcNM


谢谢你清晰的回答和工作示例。只有一个进一步的问题。对于列表中的列表,我如何引用其中一个值,例如 var test = rootObject.rows[0].values[1].value - Porkster
是的,这是正确的。您将使用 rows[0].values[1].value 访问 rows 列表中的第一个项目(索引器从 0 开始),以及 rows 列表内部的 values 列表中的第二个 Value 项目。我已更新我的答案中链接的 fiddle,以便也可以打印出来,请查看! - Shiva

2
使用类似于JSON C# Class Generator的Json到C#转换工具。
你可以使用List替换数组,并且如果你将属性名改为与Json中相匹配的,就可以省略JsonProperty属性。
这是输出结果:
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; }
}

谢谢你的回答,我认为我在以后的编程中肯定会需要它。 - Porkster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接