Swift解析OpenWeatherMap API JSON:Codable结构体构建错误排查
解决OpenWeatherMap API的Codable解析问题
首先咱们先梳理下你现有代码里的几个小问题:
- 结构体命名不规范(
cos应该换成有意义的名称,比如WeatherCondition),而且Swift里类型名称要大写开头哦 - 你的URL里用了
&,这是HTML转义字符,实际请求时要换成& - 你只定义了部分字段,如果需要解析更多内容,得把对应结构补全
下面是适配OpenWeatherMap返回JSON的Codable结构体方案,我从基础到完整版本给你展示:
基础版(仅解析你需要的weather和base字段)
如果你只需要获取天气状况的main值和base字段,结构体可以这样写:
// 对应JSON里weather数组中的单个对象 struct WeatherCondition: Codable { let main: String // 如果需要天气描述,可添加这个字段 // let description: String } // 对应整个API返回的JSON结构 struct WeatherResponse: Codable { let weather: [WeatherCondition] let base: String }
完整版(覆盖大部分常用字段)
如果需要温度、湿度、风速等更多数据,可以扩展结构体:
struct WeatherCondition: Codable { let id: Int let main: String let description: String let icon: String } struct MainWeatherData: Codable { let temp: Double let feelsLike: Double let tempMin: Double let tempMax: Double let pressure: Int let humidity: Int // 映射JSON下划线命名到Swift驼峰命名 enum CodingKeys: String, CodingKey { case temp, pressure, humidity case feelsLike = "feels_like" case tempMin = "temp_min" case tempMax = "temp_max" } } struct WindData: Codable { let speed: Double let deg: Int } struct SysData: Codable { let country: String let sunrise: TimeInterval let sunset: TimeInterval } struct WeatherResponse: Codable { let weather: [WeatherCondition] let base: String let main: MainWeatherData let wind: WindData let sys: SysData let name: String let cod: Int }
完整请求解析示例代码
把你的请求代码补全,确保能正常解析:
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() fetchWeatherData() } func fetchWeatherData() { // 注意替换URL里的&为& guard let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=warsaw&appid=5ca98c08c8abd2bf1fdbd601c3cf3d7e") else { print("无效的URL") return } let task = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in guard let data = data, error == nil else { print("获取数据失败: \(error?.localizedDescription ?? "未知错误")") return } // 可选:打印原始JSON用于调试 if let jsonString = String(data: data, encoding: .utf8) { print("原始JSON数据: \(jsonString)") } do { // 用基础版就替换成对应的WeatherResponse let weatherResponse = try JSONDecoder().decode(WeatherResponse.self, from: data) print("数据源: \(weatherResponse.base)") print("天气类型: \(weatherResponse.weather.first?.main ?? "无数据")") // 完整版可打印更多信息 // print("当前温度: \(weatherResponse.main.temp) K") // print("湿度: \(weatherResponse.main.humidity)%") // print("城市名称: \(weatherResponse.name)") } catch { print("解析失败: \(error.localizedDescription)") // 打印错误详情方便调试 print("错误详情: \(error)") } } task.resume() } }
调试小技巧
如果还是解析失败,建议先打印原始JSON数据,对比你的结构体字段是否一一对应,检查有没有拼写错误或键名不匹配的问题。
内容的提问来源于stack exchange,提问作者kuba
相关产品推荐
相关产品推荐

