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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:55:34