【问题标题】:Good way to parse this dynamic JSON解析这个动态 JSON 的好方法
【发布时间】:2016-09-27 18:45:19
【问题描述】:

我的 JSON 数据因帐户设置而异。它有一个“值”数组,可以包含零个或多个字段值数组,还有一个 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。

【问题讨论】:

  • 似乎最简单的方法是转换传入的 JSON,以便数组数组成为正确键控对象的数组。然后像往常一样解析它。
  • 额外的逗号"Acme, Inc." ],]

标签: c# arrays json dynamic


【解决方案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();
}

【讨论】:

    【解决方案2】:

    我发现你的 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;
    

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

    【讨论】:

    • 你是对的,@Mark。正确的形式是 [[...], [...], ...] (单个数组中的一组数组)
    猜你喜欢
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 1970-01-01
    • 1970-01-01
    • 2011-08-28
    • 2016-06-16
    相关资源
    最近更新 更多