Swift JSON解码报错:Scoreboard需遵循Decodable协议问题排查
问题分析与解决方案
核心问题1:泛型参数遮蔽自定义类型
你在loadNbaScoreboardData函数里声明了泛型<Scoreboard>,这个泛型占位符会直接遮蔽你自己定义的Scoreboard结构体。编译器会把函数里的所有Scoreboard当成无约束的泛型参数,而非你写的Codable结构体——这就是为什么会出现「无法找到Scoreboard类型」和「需要遵循Decodable」的错误。
核心问题2:异步任务的返回逻辑错误
URLSession.dataTask是异步执行的,函数里的retData会在网络请求完成前就被返回,此时它还未被赋值;同时闭包里的赋值操作也无法同步影响外部变量。另外fatalError(error)的用法错误,fatalError需要传入字符串,不能直接传Error实例。
修正后的完整代码
1. Codable结构体(无需修改,确保和函数在同一作用域)
struct ResultSet: Codable { var name: String var headers: [String] var rowSet: [String] } struct Scoreboard: Codable { var resultSets: [ResultSet] }
2. 修正后的请求解码函数
用闭包回调处理异步结果,去掉错误的泛型声明:
func loadNbaScoreboardData(completion: @escaping (Result<Scoreboard, Error>) -> Void) { let formatter = DateFormatter() formatter.dateFormat = "MM/dd/yyyy" let formattedDate = formatter.string(from: Date()) guard let url = URL(string: "https://stats.nba.com/stats/scoreboard/?GameDate=\(formattedDate)&LeagueID=00&DayOffset=100") else { completion(.failure(NSError(domain: "InvalidURL", code: -1, userInfo: nil))) return } var request = URLRequest(url: url) request.httpMethod = "GET" request.setValue("stats.nba.com", forHTTPHeaderField: "host") request.setValue("application/json", forHTTPHeaderField: "Accept") request.setValue("stats", forHTTPHeaderField: "x-nba-stats-origin") request.setValue("https://stats.nba.com", forHTTPHeaderField: "Referer") // 修正Referer头的错误值 URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { completion(.failure(error)) return } guard let data = data else { completion(.failure(NSError(domain: "NoData", code: -2, userInfo: nil))) return } do { let decodedData = try JSONDecoder().decode(Scoreboard.self, from: data) completion(.success(decodedData)) } catch { completion(.failure(error)) } }.resume() }
调用示例
loadNbaScoreboardData { result in switch result { case .success(let scoreboard): print("解码成功:\(scoreboard.resultSets)") case .failure(let error): print("解码失败:\(error.localizedDescription)") } }
额外说明:原代码里的Referer头值写错了,应该是完整域名https://stats.nba.com,否则可能被NBA服务器拒绝请求。
内容的提问来源于stack exchange,提问作者Omar Ebrahim
相关产品推荐
相关产品推荐

