嵌套JSON解析报错:含weather字段的Swift Codable结构体解析失败
嵌套JSON解析问题解决(含weather字段)
问题描述
解析包含weather字段的嵌套JSON时,执行try decoder.decode(Top.self, from: data)代码报错,但从结构体定义中移除weather元素后,解析就能正常工作,需要修正结构体定义和解析代码。
原始JSON示例
{"lat":39.9295,"lon":-85.608,"timezone":"America/Chicago","timezone_offset":-18000,"current":{"dt":1690514755,"sunrise":1690457901,"sunset":1690507157,"temp":302.6,"feels_like":306.89,"pressure":1015,"humidity":70,"dew_point":296.55,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":1.54,"wind_deg":0,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}]}}
错误原因
- 数组与单个对象类型不匹配:JSON中
weather是数组格式([]包裹),但原结构体CurrentJSON里将weather定义为单个WeatherJSON?对象,解析时无法完成数组到单个对象的映射,直接报错。 - 字段类型不匹配:JSON中
weather内的id是数字类型(800),但原WeatherJSON结构体里把id定义为String?,类型不匹配引发解析失败。
修正后的结构体定义
struct Top: Codable { let lat: Double let lon: Double let timezone: String? let timezone_offset: Double let current: CurrentJSON? // 属性名与JSON键名完全一致时,可省略CodingKeys } struct CurrentJSON: Codable { let dt: Int let sunrise: Int let sunset: Int let temp: Double let feels_like: Double let pressure: Int let humidity: Int let dew_point: Double let uvi: Double let clouds: Int let visibility: Int let wind_speed: Double let wind_deg: Int // 将weather改为数组类型,匹配JSON结构 let weather: [WeatherJSON]? } struct WeatherJSON: Codable { // 将id改为Int类型,匹配JSON中的数字值 let id: Int? let main: String? let description: String? let icon: String? }
修正后的解析代码
func getWeatherCurrentDay(url: URL, latitudeStr: String, longitudeStr: String, completion: @escaping (Bool, CurrentJSON?) -> ()) { let dataTask = URLSession.shared.dataTask(with: url) { responseData, response, error in guard let data = responseData, error == nil else { print("请求错误:\(error?.localizedDescription ?? "未知错误")") completion(false, nil) return } // 打印JSON字符串用于调试(可选) if let jsonString = String(data: data, encoding: .utf8) { print("JSON String:\(jsonString)") } do { let decoder = JSONDecoder() let weatherData = try decoder.decode(Top.self, from: data) // 主线程回调结果,保证UI操作安全 DispatchQueue.main.async { completion(true, weatherData.current) } } catch { // 打印具体解析错误,方便定位问题 print("解析错误:\(error)") completion(false, nil) } } dataTask.resume() }
关键说明
- 类型严格匹配:JSON中的数组必须对应Swift的
Array类型,数字对应Int/Double,字符串对应String,类型不匹配是Codable解析失败的最常见原因。 - 简化CodingKeys:当结构体属性名和JSON键名完全一致时,无需手动定义
CodingKeys,Codable会自动完成映射。 - 错误处理优化:解析时要捕获并打印具体错误信息,别只输出模糊的"error",能更快定位问题。
- 线程安全:UI相关操作必须在主线程执行,用
DispatchQueue.main.async而非sync,避免死锁风险。
内容的提问来源于stack exchange,提问作者vrao
相关产品推荐
相关产品推荐

