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

嵌套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"}]}}

错误原因

  1. 数组与单个对象类型不匹配:JSON中weather是数组格式([]包裹),但原结构体CurrentJSON里将weather定义为单个WeatherJSON?对象,解析时无法完成数组到单个对象的映射,直接报错。
  2. 字段类型不匹配: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 02:00:38