如何使用json.net将复杂的分离("列" /"数据")json反序列化为c#对象

时间:2016-08-14 22:10:22

标签: c# json json.net

我需要将以下JSON解析为PackageEntity对象的列表。

由于这个json分为Column和Data,我很难以聪明的方式这样做。

JSON看起来像:

{
  "COLUMNS": ["NSHIPMENTID", "NSHIPPINGCOMPANYID", "NUSERID", "NWEIGHT", "NHEIGHT"],

  "DATA": [
      [7474, null, 12363, "16", "2"],
      [7593, null, 12363, "64", "7"]
  ]
}

我想将其反序列化为以下类的列表:

public class PackageEntity
{
    public int NSHIPMENTID  { get; set; }
    public string NSHIPPINGCOMPANYID  { get; set; }
    public int NUSERID  { get; set; }
    public decimal NWEIGHT  { get; set; }
    public decimal NHEIGHT { get; set; }
} 

到目前为止我做了什么:

JObject JsonDe = JObject.Parse(responseString);
                int length = JsonDe.Property("DATA").Value.ToArray().Count();

                List<PackageEntity> _list = new List<PackageEntity>();

                for (int i = 0; i < length; i++)
                {
                    PackageEntity pD = new PackageEntity();
                    pD.NSHIPMENTID = JsonDe.Property("DATA").Value.ToArray()[i][0].ToString();
                    pD.NSHIPPINGCOMPANYID = JsonDe.Property("DATA").Value.ToArray()[i][1].ToString();
                    pD.NUSERID = JsonDe.Property("DATA").Value.ToArray()[i][2].ToString();
                    pD.NWEIGHT = JsonDe.Property("DATA").Value.ToArray()[i][3].ToString();
                    pD.NHEIGHT = JsonDe.Property("DATA").Value.ToArray()[i][4].ToString();
                    _list.Add(pD);
                }

1 个答案:

答案 0 :(得分:3)

您可以使用以下通用custom JsonConverter反序列化数据:

public class ColumnarDataToListConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<T>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var list = existingValue as List<T> ?? new List<T>();
        var obj = JObject.Load(reader);
        var columns = obj["COLUMNS"] as JArray;
        var data = obj["DATA"] as JArray;
        if (data == null)
            return list;
        list.AddRange(data
            .Select(item => new JObject(columns.Zip(item, (c, v) => new JProperty((string)c, v))))
            .Select(o => o.ToObject<T>(serializer)));
        return list;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后按如下方式使用:

var settings = new JsonSerializerSettings { Converters = new[] { new ColumnarDataToListConverter<PackageEntity>() } };
var list = JsonConvert.DeserializeObject<List<PackageEntity>>(responseString, settings);

请注意使用Enumerable.Zip()将列数组中的条目与数据数组的每一行中的条目配对成一个临时JObject以进行反序列化。