解析这个动态JSON的好方法

时间:2016-05-30 03:19:58

标签: c# arrays json dynamic

我的JSON数据因帐户设置而异。它有一个“values”数组,可以包含零个或多个字段值数组,以及一个columnNames数组,它给出了与值一起使用的列名。这是一个例子:

{
  "values": [
    [
      "32999000000001",
      "32999*****0001",
      "Joe",
      "Doe",
      "joe@doe.com",
      "1/1/1900",
      null,
      "1234",
      null,
      "222-111-2223",
      null,
      null,
      null,
      null,
      "UNITED STATES",
      null,
      null,
      "Acme, Inc."
    ],
    [
      "39999000000002",
      "39999*****0002",
      "Joe",
      "Schmoe",
      "joe@yahoo.com",
      "1/1/1990",
      null,
      "333-555-4444",
      null,
      "123 Some Street",
      null,
      "Michigan",
      null,
      null,
      "UNITED STATES",
      null,
      null,
      "Acme, Inc."
    ],
  ],
  "columnNames": [
    "accountNumber",
    "Acct Number",
    "First Name",
    "Last Name",
    "Email Address",
    "Date Of Hire",
    "Anniversary Date",
    "Phone Number",
    "Other Phone Number",
    "Address1",
    "Address2",
    "City",
    "State",
    "Postal Code",
    "Country",
    "Company",
    "Club ID",
    "Member Type"
  ]
}

我需要使用此数据填充业务对象数组(业务对象具有我感兴趣的JSON数据中每个列名的属性):

public class SearchResultRecord
{
    public string AccountNumber { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string EmailAddress { get; set; }
    public DateTime? DateOfHire { get; set; }
    public DateTime? AnniversaryDate { get; set; }
    public string PhoneNumber { get; set; }
    public string OtherPhoneNumber { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
    public string Country { get; set; }
    public string Company { get; set; }
    public string ClubId { get; set; }
    public string MemberType { get; set; }
}

我打算为此使用JSON.NET,我可以创建一个自定义属性来装饰每个属性,然后使用反射来将值映射到正确的属性,但我希望有一个更容易/更清洁的方式或者可能已经内置到JSON.NET中的东西我可以使用。

什么是干净,好的方法来实现这一目标?

请注意,如果有更合适的库,我使用JSON.NET。

2 个答案:

答案 0 :(得分:1)

此代码将为您进行转换:

var props = typeof(SearchResultRecord).GetProperties().ToDictionary(
                    x => x.Name, 
                    StringComparer.OrdinalIgnoreCase);
var jss = new JavaScriptSerializer();
var data = (Dictionary<string,object>)jss.DeserializeObject(json); 
var cols = ((object[])data["columnNames"]).OfType<string>()
                                          .Select((x,index) => new{index,name=x.Replace(" ","")})
                                          .Where (x => props.ContainsKey(x.name))
                                          .Select (x => new {x.index,prop=props[x.name]}).Dump();
var rows = ((object[])data["values"]).OfType<object[]>().ToArray();

foreach (var row in rows)
{
    var rowdict = cols.Where (c => row[c.index] != null).ToDictionary(c => c.prop.Name, c => row[c.index]);
    var rowjson = jss.Serialize(rowdict);
    jss.Deserialize<SearchResultRecord>(rowjson).Dump();
}

答案 1 :(得分:0)

我发现你的JSON数据结构应该如下:

{ "values": [ [...], [...], ...], "columnNames": [...] }

因此,您必须创建包装SearchResultRecord的列表:

public class SearchResultRecord
{
     // other entities here
     ...

     // nested list used to hold jagged array values
     public List<List<SearchResultRecord>> values { get; set; }
}

使用JavaScriptSerializer将锯齿状数组反序列化为预定义的通用列表:

Deserialize nested JSON array in C#

using System.Web.Script.Serialization;

SearchResultRecord model = new SearchResultRecord();
var result = new JavaScriptSerializer().Deserialize<List<List<SearchResultRecord>>>(jsonData);
model.values = result;

我建议您在反序列化过程中将列名声明(单个数组)与其值(锯齿状数组)分开,因为它们具有不同的数组大小和结构。