【问题标题】:Trying to parse JSON but got "Cannot create and populate list type"?试图解析 JSON 但得到“无法创建和填充列表类型”?
【发布时间】:2016-07-10 15:03:16
【问题描述】:

最近我决定编写一个 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:发生一个或多个错误。 ---> 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:发生一个或多个错误。 ---> 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。

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

问候, 杰克逊。

【问题讨论】:

  • 你试过“public Forecast[] Forecast { get; set; }”吗?
  • 是的,我得到了与 List 相同的结果
  • 我正在使用 DataContractJsonSerializer 并且像魅力一样工作,没有任何问题。使用预测[]
  • @x... 谢谢。现在它工作正常!

标签: c# .net json json.net


【解决方案1】:

我尝试使用一个干净的项目和来自 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; }

    }
}

【讨论】:

  • 在尝试使用自定义 IEnumerable 实现反序列化类时,我遇到了相同的错误“无法填充和解析列表类型”。添加 [JsonObject] 属性有效,我相信它向 Json.Net 表明不要将此对象视为常规列表,让我们将序列化作为任何对象处理。
【解决方案2】:

对于第二个错误,听起来您正在代码中的某处创建 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++)
{

}

【讨论】:

  • 好的,谢谢您的回复。我有点困惑,我可能已经将“预测”声明为 JArray。你的意思是我需要添加一个 JsonConverter 先转换它,然后再做其他事情?
  • @JacksonMingHu 无论您在代码中遇到该错误,断点并检查具有您的 JSON 的对象的类型。无论您在何处创建 JObject,您都可以对其进行迭代并将值分配给您的类的实例。不需要将其转换为 JArray,我将第二个循环作为示例。
猜你喜欢
  • 2021-12-19
  • 1970-01-01
  • 2019-09-30
  • 1970-01-01
  • 2016-08-23
  • 2014-01-01
  • 1970-01-01
  • 2016-07-04
  • 1970-01-01
相关资源
最近更新 更多