【问题标题】:Can't deserialize json football data无法反序列化 json 足球数据
【发布时间】:2015-05-12 18:26:09
【问题描述】:

我想创建一个使用来自 football-data.org 的数据的 Windows 窗体应用程序。这是我第一次使用 restful/JSON 并且我被卡住了。

当我尝试获取 football-data.org 提供的所有联赛时,这是您从 football-data.org api 获得的响应:response

我使用以下代码来正确获取所有数据:(lbResultBox 是一个列表框)

private void btAllLeagues_Click(object sender, EventArgs e)
{
    lbResultBox.Items.Clear();
    List<Leagues> LL = GetLeagues("soccerseasons");
    foreach (var item in LL)
    {
       lbResultBox.Items.Add(item.caption);
    }
}

public static List<Leagues> GetLeagues(string endurl)
{
    var syncClient = new WebClient();
    var content = syncClient.DownloadString(baseurl + endurl);
    return JsonConvert.DeserializeObject<List<Leagues>>(content);
}

public class Leagues
{
    public IDictionary<string,LeagueLinks> _links { get; set; }
    public string caption { get; set; }
    public string league { get; set; }
    public string year { get; set; }
    public string numberOfTeams { get; set; }
    public string numberOfGames { get; set; }
    public string lastUpdated { get; set; }
}

public class LeagueLinks
{
    public string href { get; set; }
}

这行得通。

但是当我尝试从一个联赛中获取所有球队时,这是我从 api 获得的response。我使用此代码:

private void btAllTeams_Click(object sender, EventArgs e)
{
    List<LeagueTeams> LT = GetLeagueTeams("soccerseasons/" + id + "/teams");
}

public static List<LeagueTeams> GetLeagueTeams(string endurl)
{
   var syncClient = new WebClient();
   var content = syncClient.DownloadString(baseurl + endurl);
   return JsonConvert.DeserializeObject<List<LeagueTeams>>(content);
}

public class LeagueTeams
{
    public IDictionary<string, LeagueLinks> _links { get; set; }
    public string count { get; set; }
    public IDictionary<string, LeagueTeam> teams { get; set; }
}

public class LeagueTeam
{
    public IDictionary<string, TeamLinks> _links { get; set; }
    public string name { get; set; }
    public string code { get; set; }
    public string shortName { get; set; }
    public string squadMarketValue { get; set; }
    public string crestUrl { get; set; }
}
public class TeamLinks
{
    public string href { get; set; }
}

但我收到以下错误:

Newtonsoft.Json.dll 中出现“Newtonsoft.Json.JsonSerializationException”类型的未处理异常 附加信息:无法将当前 JSON 数组(例如 [1,2,3])反序列化为 System.Collections.Generic.IDictionary`2[System.String,FootballTestApplication.LeagueTeam]' 类型,因为该类型需要 JSON 对象(例如 { "name":"value"}) 以正确反序列化。

当我查看 api 为我提供的响应时,我可以看到响应开始的方式有所不同。收集所有联赛时,它以括号 ([]) 开头和结尾,但在收集联赛中的球队时,它不以括号开头或结尾。当我自己添加括号时,我仍然得到错误。这就是我添加括号的方式:

return JsonConvert.DeserializeObject<List<LeagueTeams>>("["+content+"]");

我在这里做错了什么?

【问题讨论】:

标签: c# winforms rest


【解决方案1】:

问题在于返回的 JSON 不是ArrayListDictionary 或其他Enumerable,而是它自己的object

如果我们从该 API 链接中获取您的 JSON 并逐个元素地检查它,我们会发现您的 Type 是错误的。

您告诉 JSON 序列化器根对象是 List&lt;LeagueTeams&gt;,但它不是。它实际上是一个 LeagueTeams 对象。

如果我们对反序列化器进行了修改,并且我们对您的 LeagueTeams 类进行了一些修改(主要是您反序列化 links 属性错误的事实),那么您已经准备就绪:

public class LeagueTeams
{
    public List<IDictionary<string, string>> _links { get; set; }
    public string count { get; set; }
    public List<LeagueTeam> teams { get; set; }
}

return JsonConvert.DeserializeObject<LeagueTeams>(content);

我已附上结果图片。

附加说明

另外需要注意的是:JSON to C# 网站 (http://json2csharp.com/) 确实正确处理了这个 JSON,它实际上生成了一个几乎正确的对象,但不完全。 (虽然,生成的对象仍然可以正常工作,但它不是输入 JSON 的完全正确映射。)这部分是由于生成器的错误,还有网站的错误。它尝试为根 links 项目生成一个包含两个属性的 Link 元素的列表,而它应该使用字典列表来获得正确的映射。 (虽然,这有点令人困惑,但这是最正确的方法。)要考虑的另一件事是,是的,它可以很好地开始,但一般来说,正确的 JSON 处理需要对生成的对象进行更细致的检查保证正确性。

【讨论】:

  • 这行得通!谢谢你。我现在只有一个问题。如何在我的列表框中添加团队的“名称”?因为我的 foreach 循环得到一个 getenumerator 异常。
  • 我刚刚使用了以下代码,它确实做到了:foreach (LeagueTeam team in obj.teams) { Console.WriteLine(team.name); /* Or other operation */ }
  • 是的,谢谢,我只是想更新我的问题,因为我找到了。再次感谢您。
  • @RogierBa 没问题。很高兴我能帮上忙。
猜你喜欢
  • 1970-01-01
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-30
相关资源
最近更新 更多