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

Swift中解析含动态键的JSON报错,如何编写正确的Codable模型?

处理含动态键的JSON数据的Codable模型实现

先模拟一个符合你描述的JSON结构(包含动态球队ID、动态球员ID,以及球员的姓名、击球/投球数据):

示例JSON:

{
  "teams": {
    "4": {
      "players": {
        "3632": {
          "name": "John Doe",
          "batting_stats": {
            "average": 0.320,
            "home_runs": 12
          },
          "pitching_stats": {
            "era": 3.25,
            "strikeouts": 85
          }
        },
        "3752": {
          "name": "Jane Smith",
          "batting_stats": {
            "average": 0.285,
            "home_runs": 8
          },
          "pitching_stats": {
            "era": 2.90,
            "strikeouts": 92
          }
        }
      }
    },
    "5": {
      "players": {
        "4101": {
          "name": "Mike Johnson",
          "batting_stats": {
            "average": 0.305,
            "home_runs": 15
          },
          "pitching_stats": {
            "era": 3.50,
            "strikeouts": 78
          }
        }
      }
    }
  }
}

核心思路

动态键没法直接映射到固定属性名,所以用[String: 对应模型]的字典类型承接这些动态键,再配合基础数据模型就能正常解码。

1. 定义基础数据模型

先把球员的击球、投球数据和球员本身的模型写好:

// 击球数据模型
struct BattingStats: Codable {
    let average: Double
    let homeRuns: Int
    
    // 处理JSON里的蛇形键转驼峰命名
    enum CodingKeys: String, CodingKey {
        case average
        case homeRuns = "home_runs"
    }
}

// 投球数据模型
struct PitchingStats: Codable {
    let era: Double
    let strikeouts: Int
}

// 球员模型
struct Player: Codable {
    let name: String
    let battingStats: BattingStats
    let pitchingStats: PitchingStats
    
    enum CodingKeys: String, CodingKey {
        case name
        case battingStats = "batting_stats"
        case pitchingStats = "pitching_stats"
    }
}

2. 定义球队与顶层数据模型

球队里的球员是动态ID,用[String: Player]存储;顶层的球队也是动态ID,用[String: Team]存储:

// 球队模型
struct Team: Codable {
    let players: [String: Player]
}

// 顶层数据模型
struct BaseballData: Codable {
    let teams: [String: Team]
}

3. 解码JSON数据

直接用JSONDecoder就能正常解码,还能开启自动蛇形键转驼峰减少手动写CodingKeys的工作量:

func decodeBaseballData(from jsonData: Data) -> BaseballData? {
    do {
        let decoder = JSONDecoder()
        // 自动把JSON里的蛇形键(比如home_runs)转成Swift的驼峰命名(homeRuns)
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        let data = try decoder.decode(BaseballData.self, from: jsonData)
        return data
    } catch {
        print("解码出错:\(error)")
        return nil
    }
}

4. 提取并展示球员数据

如果需要把所有球员的信息提取出来展示,直接遍历字典即可:

// 假设你已经拿到了JSON的Data对象yourJsonData
if let baseballData = decodeBaseballData(from: yourJsonData) {
    var allPlayers: [Player] = []
    // 遍历所有球队
    for (_, team) in baseballData.teams {
        // 遍历球队里的所有球员
        for (_, player) in team.players {
            allPlayers.append(player)
        }
    }
    
    // 打印展示球员信息
    for player in allPlayers {
        print("球员姓名:\(player.name)")
        print("击球数据:命中率\(player.battingStats.average),本垒打\(player.battingStats.homeRuns)")
        print("投球数据:防御率\(player.pitchingStats.era),三振数\(player.pitchingStats.strikeouts)\n")
    }
}

内容的提问来源于stack exchange,提问作者Manjunath C.Kadani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:43:11