Swift解析met.no气象API时next系列字段为nil的问题
问题原因及解决方案
核心原因分析
出现next12Hours/next1Hours/next6Hours始终为nil但无解码错误的情况,大概率是JSON字段名与Swift结构体属性名不匹配,或者嵌套结构体层级与API返回的JSON结构不一致。因为这三个字段在结构体中被定义为可选类型,JSONDecoder遇到找不到对应字段或结构不匹配时,会直接赋值为nil而不抛出错误。
met.no的locationforecast 2.0 API返回的JSON采用蛇形命名法(比如next_1_hours),而Swift结构体默认使用驼峰命名(比如next1Hours),如果不做映射处理,解码器无法匹配对应字段。
具体解决方案
方案1:开启JSONDecoder的蛇形转驼峰自动映射
这是最简单的处理方式,无需手动编写CodingKeys,让解码器自动完成蛇形到驼峰的命名转换:
let decoder = JSONDecoder() // 关键配置:开启蛇形转驼峰策略 decoder.keyDecodingStrategy = .convertFromSnakeCase do { let forecastResponse = try decoder.decode(ForecastResponse.self, from: apiData) // 遍历时间序列数据,此时三个字段应能正常解析 for timeseries in forecastResponse.properties.timeseries { print(timeseries.data.next1Hours?.summary.symbolCode) } } catch { print("解码失败:\(error.localizedDescription)") }
方案2:手动定义CodingKeys完成字段映射
如果不想依赖自动转换,可以手动为结构体添加CodingKeys枚举,明确指定JSON字段与Swift属性的对应关系:
struct DataClass: Codable { let instant: Instant let next1Hours: Next1Hours? let next6Hours: Next6Hours? let next12Hours: Next12Hours? // 手动映射蛇形字段到驼峰属性 enum CodingKeys: String, CodingKey { case instant case next1Hours = "next_1_hours" case next6Hours = "next_6_hours" case next12Hours = "next_12_hours" } } // 嵌套结构体同样需要处理命名映射,比如Summary: struct Summary: Codable { let symbolCode: String enum CodingKeys: String, CodingKey { case symbolCode = "symbol_code" } }
方案3:检查嵌套结构体层级是否匹配API返回
确保next1Hours等字段的嵌套结构体与API返回的JSON结构完全一致。比如met.no API中next_1_hours的结构是:
"next_1_hours": { "summary": { "symbol_code": "clearsky_day" }, "details": { "precipitation_amount": 0.0 } }
对应的Swift结构体必须准确对应层级:
struct Next1Hours: Codable { let summary: Summary let details: Next1HoursDetails? } struct Next1HoursDetails: Codable { let precipitationAmount: Double }
额外验证步骤
- 打印API返回的原始JSON数据,确认
next_1_hours/next_6_hours/next_12_hours字段确实存在于响应中 - 确保结构体中这三个字段被定义为可选类型(带
?),避免因部分时间序列条目缺失字段导致解码报错 - 解码时捕获并打印完整错误信息,即使当前无报错,也能排查潜在的结构不匹配问题
内容的提问来源于stack exchange,提问作者Prebbe83
相关产品推荐
相关产品推荐

