如何使用C#中的DataContractJsonSerializer
解析下面的JSON对象?
我需要定义一个类来保存下面的JSON数据,其中包含一组混合类型的基元数组(字符串和整数):
Body:
{
"status": "failure",
"staticdata": [
[
"2013-06-01",
123
],
[
"2013-06-02",
234
],
[
"2013-06-03",
345
],
...
]
}
我尝试了以下答案并尝试阅读DataContractJsonSerializer
,
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(RootObject));
object objResponse = jsonSerializer.ReadObject(response);
RootObject jsonResponse = objResponse as RootOject;
foreach (object[] sd in jsonResponse.staticdata)
{
foreach (object o in sd)
{
//Value val = v as Value;
Value val = (Value)Convert.ChangeType(o, typeof(Value));
log.Info("date: " + val.date);
log.Info("crashCount: " + val.longValue);
}
}
但是在从对象到Value的converttype崩溃时,我在这里遗漏了一些东西。
价值低于等级:
[DataContract]
public class Value
{
[DataMember(Name = "date")]
public string date { get; set; }
[DataMember(Name = "longValue")]
public long longValue{ get; set; }
}
修改后的代码读取值(IgnoreDataMember值),然后可以读取如下:这是正确的方法吗?
object objResponse = jsonSerializer.ReadObject(response);
RootObject jsonResponse = objResponse as RootOject;
foreach (Value in jsonResponse.Values)
{
log.Info("date: " + val.date);
log.Info("longValue: " + val.longValue);
}
答案 0 :(得分:2)
如果您只想反序列化JSON,可以使用代码生成工具,例如http://json2csharp.com/或Paste JSON As Classes,并获取以下数据模型,该模型与DataContractJsonSerializer
完美配合:
public class RootObject
{
public string status { get; set; }
public List<List<object>> staticdata { get; set; }
}
object
有效,因为DataContractJsonSerializer
会自动识别并序列化已知的基本类型,例如string
和int
。
但您可能想要的是将您的"staticdata"
数组反序列化为类的列表,如下所示:
public class Value
{
public string Date { get; set; }
public int IntValue { get; set; }
}
如果是这样,您可以使用RootObject
类型的代理属性进行转换:
[DataContract]
public class RootObject
{
[DataMember]
public string status { get; set; }
[DataMember]
object[][] staticdata
{
get
{
if (Values == null)
return null;
return Values.Select(v => new object[] { v.Date, v.IntValue }).ToArray();
}
set
{
if (value == null)
return;
Values = value.Select(a => new Value
{
Date = a.Length < 1 ? null : (string)Convert.ChangeType(a[0], typeof(string), CultureInfo.InvariantCulture),
IntValue = a.Length < 2 ? 0 : (int)Convert.ChangeType(a[1], typeof(int), CultureInfo.InvariantCulture)
}
).ToList();
}
}
[IgnoreDataMember]
public List<Value> Values { get; set; }
}
<强>更新强>
在您提出的更新问题中,但是在converttype中从对象到值正在崩溃,我在这里遗漏了什么吗?
您的问题是,您尝试使用Convert.ChangeType()
将object
转换为Value
,但此方法仅适用于原始数据类型可以从字符串转换为字符串。来自docs:
ChangeType是一种通用转换方法,它将value指定的对象转换为conversionType。 value参数可以是任何类型的对象,conversionType也可以是表示任何基类或自定义类型的Type对象。 要使转换成功,值必须实现
IConvertible
接口,因为该方法只是将调用包装到适当的IConvertible
方法。
由于您的Value
类型未实现此界面,转换失败。
相反,您应该对嵌套数组中的各个条目使用Convert.ChangeType
。鉴于您的RootObject
看起来像:
public class RootObject
{
public string status { get; set; }
public object [][] staticdata { get; set; }
}
你应该这样做:
using System.Linq;
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(RootObject));
var jsonResponse = (RootObject)jsonSerializer.ReadObject(response);
var query = jsonResponse.staticdata
// For each object [] array in the outer array
.Select(a => new Value
{
// Convert the inner array to a Value, using the first element for the date and the second element for the longValueand the second element for the longValue
date = a.Length < 1 ? null : (string)Convert.ChangeType(a[0], typeof(string), CultureInfo.InvariantCulture),
longValue = a.Length < 2 ? 0 : (long)Convert.ChangeType(a[1], typeof(long), CultureInfo.InvariantCulture)
});
foreach (var val in query)
{
log.Info("date: " + val.date);
log.Info("crashCount: " + val.longValue);
}