1

初めて 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;
        }
    }
4

2 に答える 2

1

あなたが受け取っている JSON は配列だと思います。例外は、実際にOpenTSDBResponse[]が必要な場合に、 object[]OpenTSDBResponseに変換していると伝えようとしています。

これをデバッグするもう 1 つの方法は、変数variableを見て、デバッガーでその型を確認することです。もちろん、例外をスローする行はコメントアウトする必要があります。

新しいエラーへの取り組み DPS が適切な JSON 配列ではないようです。JSON 呼び出しごとにキーが異なるように見えるため、辞書に解析できます。

JSON 変換辞書をキーと値のペアのリストに変換

新しいクラス:

    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 Dictionary<string,double> TimeValues { get; set; }
    }
于 2013-08-23T03:05:17.687 に答える