试图解析JSON但得到“无法创建和填充列表类型”?

时间:2016-07-10 02:07:48

标签: c# .net json json.net

最近我决定编写一个Yahoo Weather PCL库来解析这些API(请参阅此处了解整个项目:https://github.com/huming2207/YahooWeather.NET)。

对于编码环境,我在Mac OSX 10.11.5上使用Xamarin 6.0.1和Mono 4.4.1,在Windows 10 10586上使用Visual Studio update 3.

我完成了大部分工作并且它有效,除了一件事。

Yahoo Weather API查询结果应该是这样的:

"item": {
 "title": "Conditions for Nome, AK, US at 02:00 PM AKDT",
 "lat": "64.499474",
 "long": "-165.405792",
 "link": "http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2460286/",
 "pubDate": "Sat, 09 Jul 2016 02:00 PM AKDT",
 "condition": {
  "code": "26",
  "date": "Sat, 09 Jul 2016 02:00 PM AKDT",
  "temp": "55",
  "text": "Cloudy"
 },
 "forecast": [
  {
   "code": "28",
   "date": "09 Jul 2016",
   "day": "Sat",
   "high": "55",
   "low": "50",
   "text": "Mostly Cloudy"
  },
  {
   "code": "39",
   "date": "10 Jul 2016",
   "day": "Sun",
   "high": "56",
   "low": "47",
   "text": "Scattered Showers"
  },
  {
   "code": "30",
   "date": "11 Jul 2016",
   "day": "Mon",
   "high": "53",
   "low": "48",
   "text": "Partly Cloudy"
  },
  {
   "code": "32",
   "date": "12 Jul 2016",
   "day": "Tue",
   "high": "59",
   "low": "47",
   "text": "Sunny"
  },
  {
   "code": "30",
   "date": "13 Jul 2016",
   "day": "Wed",
   "high": "58",
   "low": "50",
   "text": "Partly Cloudy"
  },
  {
   "code": "28",
   "date": "14 Jul 2016",
   "day": "Thu",
   "high": "53",
   "low": "51",
   "text": "Mostly Cloudy"
  },
  {
   "code": "30",
   "date": "15 Jul 2016",
   "day": "Fri",
   "high": "56",
   "low": "51",
   "text": "Partly Cloudy"
  },
  {
   "code": "26",
   "date": "16 Jul 2016",
   "day": "Sat",
   "high": "53",
   "low": "52",
   "text": "Cloudy"
  },
  {
   "code": "30",
   "date": "17 Jul 2016",
   "day": "Sun",
   "high": "62",
   "low": "52",
   "text": "Partly Cloudy"
  },
  {
   "code": "30",
   "date": "18 Jul 2016",
   "day": "Mon",
   "high": "56",
   "low": "47",
   "text": "Partly Cloudy"
  }
 ],
 "description": "<![CDATA[<img src=\"http://l.yimg.com/a/i/us/we/52/26.gif\"/>\n<BR />\n<b>Current Conditions:</b>\n<BR />Cloudy\n<BR />\n<BR />\n<b>Forecast:</b>\n<BR /> Sat - Mostly Cloudy. High: 55Low: 50\n<BR /> Sun - Scattered Showers. High: 56Low: 47\n<BR /> Mon - Partly Cloudy. High: 53Low: 48\n<BR /> Tue - Sunny. High: 59Low: 47\n<BR /> Wed - Partly Cloudy. High: 58Low: 50\n<BR />\n<BR />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2460286/\">Full Forecast at Yahoo! Weather</a>\n<BR />\n<BR />\n(provided by <a href=\"http://www.weather.com\" >The Weather Channel</a>)\n<BR />\n]]>",
 "guid": {
  "isPermaLink": "false"
 }
}

所以我写了一个“Forecast”和一个“Item”JsonObject类来声明Json.NET库来解析Json内容,如下所示:

这是“Item”类:

namespace YahooWeatherParser
{
    [JsonObject()]
    public class Item
    {
        [JsonProperty(PropertyName = "title")]
        public string Title { get; set; }

        [JsonProperty(PropertyName = "lat")]
        public double Latitude { get; set; }

        [JsonProperty(PropertyName = "lon")]
        public double Longitude { get; set; }

        [JsonProperty(PropertyName = "link")]
        public string Link { get; set; }

        [JsonProperty(PropertyName = "pubDate")]
        public string PublishDate { get; set; }

        [JsonProperty(PropertyName = "condition")]
        public Condition Condition { get; set; }

        [JsonProperty(PropertyName = "forecast")]
        public Forecast Forecast { get; set; }

        [JsonProperty(PropertyName = "description")]
        public string Description { get; set; }

        [JsonProperty(PropertyName = "guid")]
        public Guid Guid { get; set; }
    }
}

...这里是“预测”类:

using System;
using Newtonsoft.Json;

namespace YahooWeatherParser
{
    [JsonArray]
    public class Forecast
    {
        [JsonProperty(PropertyName = "code")]
        public int Code { get; set; }

        [JsonProperty(PropertyName = "date")]
        public string Date { get; set; }

        [JsonProperty(PropertyName = "day")]
        public string Day { get; set;}

        [JsonProperty(PropertyName = "high")]
        public int High { get; set; }

        [JsonProperty(PropertyName = "low")]
        public int Low { get; set; }

        [JsonProperty(PropertyName = "text")]
        public string Text { get; set; }

    }
}

然后我运行了我的代码,我有一个像这样的例外:

  

System.AggregateException:发生了一个或多个错误。 ---&GT; Newtonsoft.Json.JsonSerializationException:无法创建和填充列表类型YahooWeatherParser.Forecast。路径'query.results.channel.item.forecast',第1行,第1282位。

所以我用Google搜索解决方案。如果我在(在“Item”类中)

下面替换这些内容,我试过了
[JsonProperty(PropertyName = "forecast")]
public Forecast Forecast { get; set; }

为:

[JsonProperty(PropertyName = "forecast")]
public List<Forecast> Forecast { get; set; }

它给了我另一个不同的例外:

  

System.AggregateException:发生了一个或多个错误。 ---&GT;   Newtonsoft.Json.JsonSerializationException:无法反序列化   当前的JSON对象(例如{“name”:“value”})到类型中   'YahooWeatherParser.Forecast'因为类型需要JSON数组   (例如[1,2,3])正确反序列化。要修复此错误   将JSON更改为JSON数组(例如[1,2,3])或更改   反序列化类型,以便它是一个普通的.NET类型(例如,不是   原始类型,如整数,而不是像数组或类似的集合类型   List)可以从JSON对象反序列化。   JsonObjectAttribute也可以添加到类型中以强制它   从JSON对象反序列化。路径   'query.results.channel.item.forecast [0] .code',第1行,第1290位。

那么......接下来我该怎么做才能解决这个问题?非常感谢你的帮助!

此致 杰克逊。

2 个答案:

答案 0 :(得分:2)

我尝试使用一个干净的项目和来自nuget的实际newtonsoft json,你的问题就在这一行:

using System;
using Newtonsoft.Json;

namespace YahooWeatherParser
{
    [JsonObject]               // <= not [JsonArray] !!! 
    public class Forecast
    {
        [JsonProperty(PropertyName = "code")]
        public int Code { get; set; }

        [JsonProperty(PropertyName = "date")]
        public string Date { get; set; }

        [JsonProperty(PropertyName = "day")]
        public string Day { get; set;}

        [JsonProperty(PropertyName = "high")]
        public int High { get; set; }

        [JsonProperty(PropertyName = "low")]
        public int Low { get; set; }

        [JsonProperty(PropertyName = "text")]
        public string Text { get; set; }

    }
}

答案 1 :(得分:0)

有了第二个错误,听起来你在代码中的某个地方创建了一个JObject,但没有将它转换为JArray,这是必要的,因为.NET并不了解Newtonsoft JSON类型。您可以获取JArray并使用它,提取JObject并将其转换,或使用.NET框架自己的序列化类。

foreach(JObject forecast in yourJObjectQueryResult["forecast"])
{
    string theForecast = forecast.ToString(Formatting.None); 
}

for (int i=0; i < (JArray)yourJObjectQueryResult["forecast"].Count; i++)
{

}