You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Newtonsoft反序列化足球API JSON数据遇阻求助

复杂JSON反序列化问题解决思路及修复方案

问题背景

调用足球数据API获取数据时,无法使用Newtonsoft正确反序列化返回的JSON,目标是提取每个联赛的ID、名称和Logo。

返回的JSON结构

{
  "paging": {"current":1,"total":1},
  "response": [
    {
      "league":{
        "id":4,
        "name":"Euro Championship",
        "type":"Cup",
        "logo":"https://media-2.api-sports.io/football/leagues/4.png"
      },
      "country":{"name":"World","code":null,"flag":null},
      "seasons":[
        {"year":2008,"start":"2008-06-07","end":"2008-06-29","current":false,"coverage":{"fixtures":{"events":true,"lineups":true,"statistics_fixtures":false,"statistics_players":false},"standings":false,"players":true,"top_scorers":true,"top_assists":true,"top_cards":true,"injuries":false,"predictions":true,"odds":false}},
        {"year":2012,"start":"2012-06-08","end":"2012-07-01","current":false,"coverage":{"fixtures":{"events":true,"lineups":true,"statistics_fixtures":false,"statistics_players":false},"standings":false,"players":true,"top_scorers":true,"top_assists":true,"top_cards":true,"injuries":false,"predictions":true,"odds":false}},
        {"year":2016,"start":"2016-06-10","end":"2016-07-10","current":false,"coverage":{"fixtures":{"events":true,"lineups":true,"statistics_fixtures":true,"statistics_players":true},"standings":true,"players":true,"top_scorers":true,"top_assists":true,"top_cards":true,"injuries":false,"predictions":true,"odds":false}},
        {"year":2020,"start":"2019-03-21","end":"2021-07-11","current":true,"coverage":{"fixtures":{"events":true,"lineups":true,"statistics_fixtures":true,"statistics_players":true},"standings":true,"players":true,"top_scorers":true,"top_assists":true,"top_cards":true,"injuries":false,"predictions":true,"odds":false}}
      ]
    }
  ]
}

已定义的C#类

public class FootballCountryModel
{
    [JsonProperty("id")]
    public int ID { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }
    
    [JsonProperty("logo")]
    public string Logo { get; set; }
}

public class Results
{
    [JsonProperty("league")]
    public Dictionary<string, FootballCountryModel> JsonResults { get; set; }
}

public class JsonRootObject
{
    [JsonProperty("response")]
    public Results Rslt { get; set; }
}

public class LeaguesDeserializedModel
{
    [JsonProperty("parameters")]
    public object Parameters { get; set; }

    [JsonProperty("errors")]
    public object Errors { get; set; }
    
    [JsonProperty("results")]
    public int Results { get; set; }
    
    [JsonProperty("paging")]
    public object Pagin { get; set; }
    
    [JsonProperty("response")]
    public List<FootballCountryModel> Response { get; set; }
}

当前反序列化代码

dynamic jsonObj = JsonConvert.DeserializeObject<Results>(response.Content);

反序列化失败原因

  1. 层级不匹配:JSON的response是数组,每个元素包含league对象,但定义的Results类将league映射为Dictionary<string, FootballCountryModel>,完全不符合结构;且直接用Results反序列化,未匹配JSON的根层级。
  2. 类型错误:LeaguesDeserializedModel中的Response直接定义为List<FootballCountryModel>,跳过了JSON中response元素里的league嵌套层级,导致无法正确映射。

解决思路与修复方案

1. 修正类结构(严格匹配JSON层级)

只保留需要的字段,忽略无关内容:

// 对应JSON中的league对象,复用原有字段定义
public class FootballLeagueModel
{
    [JsonProperty("id")]
    public int ID { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }
    
    [JsonProperty("logo")]
    public string Logo { get; set; }
}

// 对应response数组中的单个元素,仅保留需要的league字段
public class LeagueResponseItem
{
    [JsonProperty("league")]
    public FootballLeagueModel League { get; set; }
}

// 对应JSON根对象,包含paging和response数组
public class LeagueRootModel
{
    [JsonProperty("paging")]
    public PagingModel Paging { get; set; }

    [JsonProperty("response")]
    public List<LeagueResponseItem> Response { get; set; }
}

// 可选:如果需要paging数据,定义对应类,否则可改为object类型
public class PagingModel
{
    [JsonProperty("current")]
    public int Current { get; set; }

    [JsonProperty("total")]
    public int Total { get; set; }
}

2. 正确的反序列化代码

// 反序列化为根对象类型
var root = JsonConvert.DeserializeObject<LeagueRootModel>(response.Content);

// 提取所有联赛信息
var leagues = root.Response.Select(item => item.League).ToList();

// 示例:遍历输出联赛数据
foreach (var league in leagues)
{
    Console.WriteLine($"ID: {league.ID}, Name: {league.Name}, Logo: {league.Logo}");
}

核心思路总结

  • 层级严格匹配:类的嵌套结构必须和JSON的键值层级完全对应,不能跳过中间节点;
  • 类型精准对应:JSON数组对应List<T>,单个对象对应具体类,避免错误使用Dictionary或其他不匹配类型;
  • 按需定义字段:不需要的字段可以不定义,Newtonsoft会自动忽略,减少类的复杂度;
  • 显式字段映射:用JsonProperty确保C#属性名和JSON键名一致,避免因命名规范差异导致映射失败。

内容的提问来源于stack exchange,提问作者LyuboWorking

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 11:37:47