1

我第一次处理 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;
        }
    }
4

2 回答 2

1

我相信您收到的 JSON 是一个数组。例外是当您真的想要OpenTSDBResponse[]时,您正在将object[]转换为OpenTSDBResponse

另一种调试方法是查看变量变量并查看它在调试器中的类型。当然,引发异常的行需要被注释掉。

处理新错误 看起来 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 回答
0
You can such so modify your Json Data and your C# Code,for example
    [{
    "metric":"tcollector.collector.lines_sent",
    "tags":
    {
    "host":"ubuntu1"
    },
    "aggregateTags":["collector"],
    "dps":
    [
    {"Time":"1377050434","Value":1271779.0},
    {"Time":"1377050554","Value":1272502.0}        
    ]
    }]
c# Code:        
You provide the data is an Array,so when you deserialize the string,you must such so use generic format of deserializeobject

    object obj=Newtonsoft.Json.JsonConvert.DeserializeObject<List<OpenTSDBResponse>>(json.ToString());
于 2013-08-23T03:06:56.180 回答