C# Json.NET:反序列化 json 数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15507088/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 17:01:18  来源:igfitidea点击:

Json.NET: deserialize json arrays

c#jsonjson.net

提问by t313

I'm trying to process a JSON structure with Json.NET and encountered some issues:

我正在尝试使用 Json.NET 处理 JSON 结构并遇到一些问题:

My classes don't work when a JSON contains an unnamed array.

当 JSON 包含未命名数组时,我的类不起作用。

Json Example:

JSON 示例:

{
    "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:

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:

我的代码:

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

I'm not sure why I don't get an object containing the data of the "Measurment" child-array. If I insert named values, it works...

我不确定为什么我没有得到一个包含“测量”子数组数据的对象。如果我插入命名值,它会起作用......

回答by I4V

You are almost there. Just use

你快到了。只需使用

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

instead of

代替

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

回答by Jevgenij Nekrasov

First of all, you do not really need to name all the properties of your Measurementclass exactly as they are presented in MyJsonString. You can use JsonPropertyattribute and decorate your class properties.

首先,您实际上并不需要Measurement完全按照MyJsonString. 您可以使用JsonProperty属性并装饰您的类属性。

Another thing is if you want to deserialize part of your MyJsonStringand extract only array of Measurement, you should provide correct T type for Deserializemethod (in your case it's IEnumerable<Measurement>.

另一件事是,如果你想反序列化的一部分MyJsonString,而只提取的数组Measurement,你应该提供正确的T类Deserialize方法(在你的情况下,它是IEnumerable<Measurement>

The following code should help:

以下代码应该会有所帮助:

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

回答by Raymond

So I was struggling for quite some time to get this working. However in the end the solution is not so difficult. Hopefully with my response I will help some people.

所以我挣扎了很长一段时间才能让它发挥作用。然而,最终解决方案并没有那么困难。希望我的回答能帮助到一些人。

The solution in my case was

在我的情况下的解决方案是

  1. Install JSON.net into your project by using nu.get
  2. Make your JSON object including array's in array's, etc. Be sure that the format of the object is correct! Example...
  1. 使用 nu.get 将 JSON.net 安装到您的项目中
  2. 使您的 JSON 对象包括数组中的数组等。请确保对象的格式正确!例子...

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

{“产品信息”:[

  {
      "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..."
                          }
                         ]
  }
]
}
  1. Go to json2csharp.com and copy your JSON object into the input box and click on the generate button. Copy the csharp model (this was actually the key to solve my struggle!) generated into your ViewModel.
  2. In my case the primary class of all generated classes by json2csharp.com was the RootObject and looked like 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; }
    }
    
  3. Then use the following code in the controller (just copied the complete 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();
            }
        }
    }
    
  1. 转到 json2csharp.com 并将您的 JSON 对象复制到输入框中,然后单击生成按钮。将生成的 csharp 模型(这实际上是解决我的难题的关键!)复制到您的 ViewModel 中。
  2. 在我的情况下,json2csharp.com 生成的所有类的主要类是 RootObject,如下所示

    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; }
    }
    
  3. 然后在控制器中使用以下代码(这里只是复制了完整的文件)

    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's in array's etc. Hope that you found my solution helpful, note I'm not a die hard programmer so if I miss things on efficency I hope to recieve some tips from you to improve this code...

现在一切正常,数组在数组中等等。希望你发现我的解决方案有帮助,注意我不是一个顽固的程序员,所以如果我错过了效率方面的事情,我希望从你那里得到一些提示来改进这段代码......

Best regards, Raymond

最好的问候,雷蒙德

回答by Tidy

I use a very simple method to Deserialize Json Arrays. Instead of using a ton of public classes with numerous public variables. I just use a Dynamic object and pass json as an object to JSONConvert.DeserializeObject.

我使用一种非常简单的方法来反序列化 Json 数组。而不是使用具有众多公共变量的大量公共类。我只是使用动态对象并将 json 作为对象传递给 JSONConvert.DeserializeObject。

This is how it would work. Say I have the following JSON:

这就是它的工作方式。假设我有以下 JSON:

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

I can pass string json to the JSONConvert.DeserializeObject.

我可以将字符串 json 传递给 JSONConvert.DeserializeObject。

dynamic outputArray = JsonConvert.DeserializeObject(json);

Then using the dynamic item that was just created I can collect Json data like so.

然后使用刚刚创建的动态项目,我可以像这样收集 Json 数据。

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

If you have an array inside your Json you can use

如果您的 Json 中有一个数组,则可以使用

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

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

在没有一组公共变量的情况下,很容易更改从何处提取数据……如果需要,您仍然可以将值保存到公共变量中。

The following is how I use the complete 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        
        }