我第一次处理 JSON 并从 OpenTSDB 获取数据。我创建了 ac# 类以将 JSON 反序列化为,但我收到错误“无法反序列化当前 JSON 数组”,如下所述。
我获取 JSON 的 c# 代码:
var request = WebRequest.Create("http://localhost:4242/api/query?start=2013/08/21-12:00:00&end=2013/08/22-12:00:00&m=sum:tcollector.collector.lines_sent&o=&yrange=%5B0:%5D&wxh=924x773");
request.ContentType = "application/json; charset=utf-8";
string text;
try
{
var response = (HttpWebResponse) request.GetResponse();
using (var sr = new StreamReader(response.GetResponseStream()))
{
text = sr.ReadToEnd();
}
uxResponse.Text = text;
OpenTSDBResponse myObject = (OpenTSDBResponse)Newtonsoft.Json.JsonConvert.DeserializeObject(text, typeof(OpenTSDBResponse));
var variable = Newtonsoft.Json.JsonConvert.DeserializeObject(text);
//var tester = myObject;
}
catch (Exception ex)
{
uxResponse.Text = GetFullExceptionMessage(ex);
}
我从上述代码中收到的 JSON(即“文本”变量):
[{
"metric":"tcollector.collector.lines_sent",
"tags":
{
"host":"ubuntu1"
},
"aggregateTags":["collector"],
"dps":
{
"1377050434":1271779.0,
"1377050494":1272073.0,
"1377050554":1272502.0,
"1377050614":1273632.0,
"1377050674":1273867.0
}
}]
我的 C# 课程
internal class OpenTSDBResponse
{
[JsonProperty("metric")]
public string Metric { get; set; }
[JsonProperty("tags")]
public Tags Tags { get; set; }
[JsonProperty("aggregateTags")]
public string[] AggregateTags { get; set; }
[JsonProperty("dps")]
public List<TimeValue> TimeValues { get; set; }
}
internal class Tags
{
[JsonProperty("host")]
public string Host { get; set; }
}
internal class TimeValue
{
[JsonProperty("Time")]
public double Time { get; set; }
[JsonProperty("Value")]
public double Value { get; set; }
}
反序列化对象时的错误:
无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型“MyNamespace.OpenTSDBResponse”,因为该类型需要 JSON 对象(例如 {"name":"value"})才能正确反序列化。修复此错误要么将 JSON 更改为 JSON 对象(例如 {"name":"value"}),要么将反序列化类型更改为数组或实现集合接口的类型(例如 ICollection、IList),例如可以从JSON 数组。也可以将 JsonArrayAttribute 添加到类型以强制它从 JSON 数组反序列化。Path '', line 1, position 1。
附加信息
我使用 codeproject 反序列化 JSON 项目来创建我的基本类,但它为每个 '"1377050434":1271779.0' 创建了一个新的 c# 属性,因此我更新为使用我的 TimeValue 类。http://www.codeproject.com/Tips/79435/Deserialize-JSON-with-C
问题:
如何将其放入适当的 c# 类结构中?
针对以下用户评论的附加信息:
bjaminn 的评论: 我相信您收到的 JSON 是一个数组。例外是当您真正想要 OpenTSDBResponse[] 时,您正在将 object[] 转换为 OpenTSDBResponse。另一种调试方法是查看变量变量并查看它在调试器中的类型。当然,引发异常的行需要被注释掉。
结果:我像这样修改了反序列化
OpenTSDBResponse[] myObject = (OpenTSDBResponse[])Newtonsoft.Json.JsonConvert.DeserializeObject(text, typeof(OpenTSDBResponse[]));
但是当我运行它时收到以下错误:
无法将当前 JSON 对象(例如 {"name":"value"})反序列化为类型“System.Collections.Generic.List`1[MyNamespace.OpenTSDBResponseJsonTypes.TimeValue]”,因为该类型需要 JSON 数组(例如 [1, 2,3]) 以正确反序列化。要修复此错误,请将 JSON 更改为 JSON 数组(例如 [1,2,3])或更改反序列化的类型,使其成为普通的 .NET 类型(例如,不是原语可以从 JSON 对象反序列化的整数类型,而不是数组或列表等集合类型。JsonObjectAttribute 也可以添加到类型中以强制它从 JSON 对象反序列化。路径 '[0].dps.1377050434',第 1 行,位置 121。
关于其他 JSON 新手的工作解决方案的附加说明 我在我的字典类中添加了另一个属性,因为它实际上是“unix-time-stamp-data”、“Value”。这使我可以使用日期时间/值在 c# 中工作。可能有更好的投射方法,但这不会对我的场景造成任何明显的性能问题。
[JsonProperty("dps")]
public Dictionary<string, double> TimeValues { get; set; }
public List<TimeValue> DataPoints
{
get
{
List<TimeValue> times = new List<TimeValue>();
DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
foreach (var item in TimeValues)
{
times.Add(new TimeValue
{
Time = dtDateTime.AddSeconds(double.Parse(item.Key)).ToLocalTime(),
Value = item.Value
});
}
return times;
}
}