首先使用C#Json.NET对带有变量名的Json数组进行反序列化

Mot*_*aTL 2 c# serialization json json.net

我从人口普查局的公共场所获得了一个不规则的JSON阵列.变量名都在第一个元素中,我无法反序列化它.

http://api.census.gov/data/2014/pep/agesex?get=AGE,POP,SEX&for=us:*&DATE=7

给我这样的JSON:

[["AGE","POP","SEX","DATE","us"],
["0","3948350","0","7","1"],
["1","3962123","0","7","1"],
["2","3957772","0","7","1"],
["3","4005190","0","7","1"],
["4","4003448","0","7","1"],
["5","4004858","0","7","1"],
["6","4134352","0","7","1"],
["7","4154000","0","7","1"]]
Run Code Online (Sandbox Code Playgroud)

我可以使用以下方法成功反序列化:

var test1 = JsonConvert.DeserializeObject<String[][]>(jsonStr);
Run Code Online (Sandbox Code Playgroud)

但是,我试图将它反序列化为这样的类:

public class TestClass
{
    public string AGE { get; set; }
    public string POP { get; set; }
    public string SEX { get; set; }
    public string DATE { get; set; }
    public string us { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试这样做:

var test2 = JsonConvert.DeserializeObject<TestClass[]>(jsonStr);
Run Code Online (Sandbox Code Playgroud)

但我得到以下异常:

Newtonsoft.Json.dll中出现"Newtonsoft.Json.JsonSerializationException"类型的异常,但未在用户代码中处理

附加信息:无法创建和填充列表类型TestClass.路径'[0]',第1行,第2位.

小智 6

这有两个部分.

首先是将JSON转换为C#中可用的数据,第二个是将数据转换为漂亮的对象.

这是以下代码的dotNetFiddle.net工作示例:https://dotnetfiddle.net/Cr0aRL

JSON中的每一行都由一个字符串数组组成.所以这是一个字符串数组的数组.在C#中可以写成string [] [].

因此,要使用JSON.Net将JSON转换为可用数据,您可以执行以下操作:

    var json = "[[\"AGE\",\"POP\",\"SEX\",\"DATE\",\"us\"],[\"0\",\"3948350\",\"0\",\"7\",\"1\"],[\"1\",\"3962123\",\"0\",\"7\",\"1\"],[\"2\",\"3957772\",\"0\",\"7\",\"1\"],[\"3\",\"4005190\",\"0\",\"7\",\"1\"],[\"4\",\"4003448\",\"0\",\"7\",\"1\"],[\"5\",\"4004858\",\"0\",\"7\",\"1\"],[\"6\",\"4134352\",\"0\",\"7\",\"1\"],[\"7\",\"4154000\",\"0\",\"7\",\"1\"]]";
    var rawData = JsonConvert.DeserializeObject<string[][]>(json);
Run Code Online (Sandbox Code Playgroud)

接下来就是将数据转换为对象.

第一行是包含列名的标题,因此我们要抓取它,然后找出每个列名的列索引.

    var headerRow = rawData.First();    

    var ageIndex = Array.IndexOf(headerRow, "AGE");
    var popIndex = Array.IndexOf(headerRow, "POP");
    var sexIndex = Array.IndexOf(headerRow, "SEX");
    var dateIndex = Array.IndexOf(headerRow, "DATE");
    var usIndex = Array.IndexOf(headerRow, "us");
Run Code Online (Sandbox Code Playgroud)

现在我们有索引,我们需要获取每一行,并将其转换为适当的对象.我已经使用了LINQ,因为它非常擅长以清晰的方式表示数据处理.

    var testData = rawData
        .Skip(1) //The first row is a header, not data
        .Select(dataRow => new TestClass()
        {
            AGE = dataRow[ageIndex],
            POP = dataRow[popIndex],
            SEX = dataRow[sexIndex],
            DATE = dataRow[dateIndex],
            us = dataRow[usIndex]
        });
Run Code Online (Sandbox Code Playgroud)

最后进行一些测试,以确保您拥有您期望的数据.

    //Get the second data row as an example
    var example = testData.Skip(1).First();

    //Output example POP to check value
    Console.WriteLine(example.POP);
Run Code Online (Sandbox Code Playgroud)

以上所有内容都非常手动.

你必须知道你的预期,您手动查找索引什么标题,然后手动行映射为对象.

一个简单的用例很可能这样做很好.但是在更大和/或更复杂的系统中,您可能需要/需要自动执行这些步骤.

自动执行这些步骤是可能的,但超出了本答案的范围,因为您如何处理它可能取决于许多不同的因素.