[英]How to deserialize a JSON array into an object using Json.Net?
我有一个带有JSON数组的有效JSON对象。 JSON数组没有花括号,并且包含逗号分隔的混合类型列表。 看起来像这样:
{
"ID": 17,
"Days": 979,
"Start_Date": "10/13/2012",
"End_Date": "11/12/2012",
"State": "",
"Page": 1,
"Test": "Valid",
"ROWS": [
[441210, "A", "12/31/2009", "OK", "Done", "KELLEY and Co'", "12/31/2009", "06/29/2010", "TEXAS", "Lawyers", 6, "", "<img src=\"/includes/images/Icon_done.gif\" border=\"0\" alt=\"Done\" title=\"Done\" />"],
[441151, "B", "12/31/2009", "No", "In-process", "Sage & Co", "12/31/2009", "06/29/2010", "CALIFORNIA", "Realtor", 6, "", "<img src=\"/includes/images/Icon_InProcess.gif\" border=\"0\" alt=\"In Process\" title=\"In Process\" />"]
]
}
我创建了一个反映JSON结构的类,并为复杂数组提供了一个List:
class myModel
{
public int ID { get; set; }
public int Days { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string State { get; set; }
public string Page { get; set; }
public string Test { get; set; }
List<ChildModel> Rows { get; set; }
}
我也用列表列表进行了测试:
List<List<ChildModel>> Rows { get; set; }
子模型如下所示:
class ChildModel
{
public int ID { get; set; }
public string StatusId { get; set; }
public DateTime ContactDate { get; set; }
public string State { get; set; }
public string Status { get; set; }
public string CustomerName { get; set; }
public DateTime WorkStartDate { get; set; }
public DateTime WorkEndDate { get; set; }
public string Territory { get; set; }
public string CustType { get; set; }
public int JobOrder { get; set; }
public string Filler { get; set; }
public string Link { get; set; }
}
在我的program.cs文件中,我像这样反序列化它:
using (StreamReader r = new StreamReader(@"D:\01.json"))
{
myModel items = JsonConvert.DeserializeObject<myModel>(r.ReadToEnd());
}
当我运行该程序时,子对象(Rows)始终为null
。 我究竟做错了什么?
使用它可以将数据反序列化为json对象...
public class Rootobject
{
public int ID { get; set; }
public int Days { get; set; }
public string Start_Date { get; set; }
public string End_Date { get; set; }
public string State { get; set; }
public int Page { get; set; }
public string Test { get; set; }
public object[][] ROWS { get; set; }
}
...然后创建一个实用程序函数,将object[][]
转换为所需的目标对象...
(使用Visual Studio创建:编辑->选择性粘贴-> JSON类)
Json.Net没有将数组自动映射到类的功能。 为此,您需要一个自定义JsonConverter
。 这是一个应该为您工作的通用转换器。 它使用自定义[JsonArrayIndex]
属性来标识类中的哪些属性与数组中的哪些索引相对应。 如果JSON更改,这将使您可以轻松地更新模型。 另外,您可以安全地忽略类中不需要的属性,例如Filler
。
这是代码:
public class JsonArrayIndexAttribute : Attribute
{
public int Index { get; private set; }
public JsonArrayIndexAttribute(int index)
{
Index = index;
}
}
public class ArrayToObjectConverter<T> : JsonConverter where T : class, new()
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(T);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JArray array = JArray.Load(reader);
var propsByIndex = typeof(T).GetProperties()
.Where(p => p.CanRead && p.CanWrite && p.GetCustomAttribute<JsonArrayIndexAttribute>() != null)
.ToDictionary(p => p.GetCustomAttribute<JsonArrayIndexAttribute>().Index);
JObject obj = new JObject(array
.Select((jt, i) =>
{
PropertyInfo prop;
return propsByIndex.TryGetValue(i, out prop) ? new JProperty(prop.Name, jt) : null;
})
.Where(jp => jp != null)
);
T target = new T();
serializer.Populate(obj.CreateReader(), target);
return target;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
要使用转换器,您需要标记您的ChildModel
类,如下所示:
[JsonConverter(typeof(ArrayToObjectConverter<ChildModel>))]
class ChildModel
{
[JsonArrayIndex(0)]
public int ID { get; set; }
[JsonArrayIndex(1)]
public string StatusId { get; set; }
[JsonArrayIndex(2)]
public DateTime ContactDate { get; set; }
[JsonArrayIndex(3)]
public string State { get; set; }
[JsonArrayIndex(4)]
public string Status { get; set; }
[JsonArrayIndex(5)]
public string CustomerName { get; set; }
[JsonArrayIndex(6)]
public DateTime WorkStartDate { get; set; }
[JsonArrayIndex(7)]
public DateTime WorkEndDate { get; set; }
[JsonArrayIndex(8)]
public string Territory { get; set; }
[JsonArrayIndex(9)]
public string CustType { get; set; }
[JsonArrayIndex(10)]
public int JobOrder { get; set; }
[JsonArrayIndex(12)]
public string Link { get; set; }
}
然后,只需像往常一样反序列化,它就可以按照您想要的方式工作。 这是一个演示: https : //dotnetfiddle.net/n3oE3L
注意:我没有实现WriteJson
,因此,如果您将模型序列化回JSON,它将不会序列化回数组格式。 相反,它将使用默认的对象序列化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.