Swift中JSONDecode解码数组/字典失败问题求助
解决Swift中JSONDecoder解码地震API返回数据的类型不匹配问题
你的错误提示已经说得很清楚了:你尝试把返回的JSON解码成[earthquakeResults].self(数组类型),但实际API返回的是一个包含earthquakes数组的顶层字典,这就导致了类型不匹配的崩溃。下面是具体的修复步骤:
1. 调整Codable结构体定义
首先,我们需要定义一个顶层结构体来匹配API返回的JSON结构,同时修正结构体的命名(遵循Swift大驼峰命名规范),并补全原来注释的字段(API返回的eqid和src都是字符串类型,不需要用Any):
// 匹配API返回的顶层字典结构 struct EarthquakeResponse: Codable { let earthquakes: [EarthquakeResult] } // 单个地震数据的结构体 struct EarthquakeResult: Codable { let datetime: String let depth: String let eqid: String let lat: String let lng: String let magnitude: String let src: String }
2. 修改解码逻辑
接下来调整你的网络请求完成后的解码代码,主要做这几个优化:
- 用
do-catch替代危险的try!,避免解码失败直接崩溃 - 解码顶层的
EarthquakeResponse结构体,再取出内部的地震数组 - 安全处理数组为空的情况,避免索引越界
修改后的代码如下:
let urlAsString = "http://api.geonames.org/earthquakesJSON?north=\(north)&south=\(south)&east=\(east)&west=\(west)&username=antoniogomez" guard let url = URL(string: urlAsString) else { print("Invalid URL") return } let urlSession = URLSession.shared let jsonQuery = urlSession.dataTask(with: url, completionHandler: { data, response, error -> Void in // 处理请求错误 if let error = error { print(error.localizedDescription) return } // 确保数据不为空 guard let data = data else { print("No data received from API") return } do { let decoder = JSONDecoder() // 解码顶层的EarthquakeResponse let apiResponse = try decoder.decode(EarthquakeResponse.self, from: data) let earthquakeResults = apiResponse.earthquakes print("Fetched \(earthquakeResults.count) earthquakes") // 安全获取第一个地震数据(避免数组为空时崩溃) if let firstEarthquake = earthquakeResults.first { let dt = firstEarthquake.datetime let dp = firstEarthquake.depth let lt = firstEarthquake.lat let lg = firstEarthquake.lng let mag = firstEarthquake.magnitude let res = "Results : \(dt) \(dp) \(lt) \(lg) \(mag)" print(res) } else { print("No earthquakes found in the requested area") } } catch { // 捕获并打印解码错误 print("JSON Decoding Error: \(error.localizedDescription)") print("Detailed error info: \(error)") } }) jsonQuery.resume()
额外说明
- 你之前用
JSONSerialization无法获取字段的原因,大概率也是因为没有先从顶层字典中取出earthquakes数组,直接去取字段当然找不到。 - 永远不要用
try!处理解码操作,一旦API返回结构变化或数据异常,你的App会直接崩溃,do-catch是更安全的处理方式。 - Swift的Codable对字符串、数字等基础类型的兼容性很好,只要API返回的字段类型和你定义的结构体字段类型匹配,就能正常解码。
内容的提问来源于stack exchange,提问作者Code Gomez
相关产品推荐
相关产品推荐

