初めて JSON を扱い、OpenTSDB からデータを取得しています。JSON を逆シリアル化する ac# クラスを作成しましたが、以下で説明するように、「現在の 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"}) に変更するか、逆シリアル化された型を配列、または List などのコレクション インターフェイスを実装する型 (例: ICollection、IList) に変更します。 JSON 配列。JsonArrayAttribute を型に追加して、強制的に JSON 配列から逆シリアル化することもできます。パス ''、行 1、位置 1.
追加情報
codeproject deserialize JSON プロジェクトを使用して基本的なクラスを作成しましたが、「1377050434」:1271779.0 ごとに新しい c# プロパティが作成されたため、TimeValue クラスを使用するように更新しました。http://www.codeproject.com/Tips/79435/Deserialize-JSON-with-C
質問:
これを適切なC#クラス構造にするにはどうすればよいですか?
以下のユーザーのコメントに対する追加情報:
bjaminn のコメント: あなたが受け取っている JSON は配列だと思います。例外は、実際に OpenTSDBResponse[] が必要な場合に、オブジェクト [] を OpenTSDBResponse に変換しようとしているということです。これをデバッグするもう 1 つの方法は、変数 variable を見て、デバッガーでその型を確認することです。もちろん、例外をスローする行はコメントアウトする必要があります。
結果:このようにデシリアライズを変更しました
OpenTSDBResponse[] myObject = (OpenTSDBResponse[])Newtonsoft.Json.JsonConvert.DeserializeObject(text, typeof(OpenTSDBResponse[]));
しかし、実行すると次のエラーが発生しました。
型には JSON 配列が必要なため (例: [1,このエラーを修正するには、JSON を JSON 配列 ([1,2,3] など) に変更するか、逆シリアル化された型を通常の .NET 型 (プリミティブではない型) に変更します。配列やリストのようなコレクション型ではなく、整数のような型) は、JSON オブジェクトから逆シリアル化できます。JsonObjectAttribute を型に追加して、強制的に JSON オブジェクトから逆シリアル化することもできます。パス '[0].dps.1377050434'、行 1、位置 121。
JSON のその他の新しい機能に関する追加の注意事項 実際には「unix-time-stamp-data」、「Value」であるため、Dictionary のクラスに別のプロパティを追加しました。これにより、日時/値を使用して 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;
}
}