Swift Codable解码JSON遇缺失键仍报错,已用Optional无效如何解决
Swift Codable 缺失键场景解码失败问题解决方案
核心问题定位
你当前解码失败的根本原因是类型不匹配,并非缺失键导致。你提供的JSON样例中,dynamic_obj数组第一条对象的latitude、longitude字段为Double数值类型,但你的Dynamic_obj结构体将这两个属性声明为String类型,解码时类型不匹配抛出错误。
你当前使用的decodeIfPresent本身就是Codable处理缺失键的标准方案,只要字段类型匹配,缺失对应键时会自动赋值为nil或者你设置的默认值,不会触发解码失败。
修复方案
方案1:属性类型改为Double,按需转字符串(推荐)
修改Dynamic_obj的属性声明和解码逻辑即可:
struct Dynamic_obj : Codable { var dt : String? var url : String? let desc : String? var flag : Int? let count : String? let field : String? let visible : Bool? var bankname : String = "NA" var pdfPassword : String = "NA" // 修改属性类型为Double可选 var latitude : Double? var longitude : Double? var address : String = "NA" // CodingKeys可简化,无需重复赋值相同名称的键 enum CodingKeys: String, CodingKey { case dt, url, desc, flag, count, field, visible case bankname, pdfPassword, latitude, longitude, address } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) dt = try values.decodeIfPresent(String.self, forKey: .dt) url = try values.decodeIfPresent(String.self, forKey: .url) desc = try values.decodeIfPresent(String.self, forKey: .desc) flag = try values.decodeIfPresent(Int.self, forKey: .flag) count = try values.decodeIfPresent(String.self, forKey: .count) field = try values.decodeIfPresent(String.self, forKey: .field) visible = try values.decodeIfPresent(Bool.self, forKey: .visible) bankname = try values.decodeIfPresent(String.self, forKey: .bankname) ?? "NA" pdfPassword = try values.decodeIfPresent(String.self, forKey: .pdfPassword) ?? "NA" // 改解码类型为Double,缺失则赋值nil latitude = try values.decodeIfPresent(Double.self, forKey: .latitude) longitude = try values.decodeIfPresent(Double.self, forKey: .longitude) address = try values.decodeIfPresent(String.self, forKey: .address) ?? "NA" } // 若需要字符串格式的经纬度,可新增计算属性 var latitudeStr: String { guard let lat = latitude else { return "NA" } return "\(lat)" } var longitudeStr: String { guard let lon = longitude else { return "NA" } return "\(lon)" } }
方案2:保持属性为String类型,解码时做类型兼容
如果业务要求必须把经纬度存为String类型,可在解码时增加类型判断自动转换:
init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) // 其他属性解码逻辑保持不变 // ... // 兼容数值类型的经纬度,自动转字符串 if let latDouble = try values.decodeIfPresent(Double.self, forKey: .latitude) { latitude = "\(latDouble)" } else { latitude = try values.decodeIfPresent(String.self, forKey: .latitude) ?? "NA" } if let lonDouble = try values.decodeIfPresent(Double.self, forKey: .longitude) { longitude = "\(lonDouble)" } else { longitude = try values.decodeIfPresent(String.self, forKey: .longitude) ?? "NA" } }
调试优化建议
后续遇到解码错误时,可在catch块打印完整错误信息,能直接定位到具体出错的字段和原因:
catch { print("解码错误:\(error)") }
内容的提问来源于stack exchange,提问作者karthikeyan
相关产品推荐
相关产品推荐

