升级至Xcode 9.3后JSON数据类型转换异常问题咨询
嘿,这个问题我帮不少开发者踩过坑,其实根源是Xcode 9.3对应的Swift 4.1版本里,JSON序列化的类型转换规则变得更严格了,咱们一步步说清楚:
1. JSON数字类型的本质
首先得明确:JSON标准里并没有单独的Float类型,所有数字都统一归为Number类型。苹果Foundation框架的JSONSerialization默认会把JSON里的Number解析成Double——这是因为Double的精度更高,能覆盖JSON中所有可能的数字取值范围,从根源上避免精度丢失问题。
2. 旧版本Swift的“宽松”转换逻辑
在Xcode 9.2(对应Swift 4.0及更早版本)中,Swift的类型转换系统对字典这类集合类型的处理比较灵活:当你尝试用as? [String : Float]强转时,它会逐个检查字典里的Double值,尝试把它们转换为Float,只要所有值都能成功转换,整个强转就会通过。
3. Swift 4.1之后的严格检查
但到了Swift 4.1(Xcode 9.3),苹果收紧了集合类型的类型转换规则:现在as?只会检查集合的顶层类型是否匹配,不会再递归地转换内部元素的类型。因为JSON解析出来的字典实际是[String : Double]类型,所以as? [String : Float]会直接失败,必须明确用Double来匹配底层的实际类型。
可选的替代方案
如果你的代码确实需要用Float类型,也可以先解析成[String : Double],再手动转换为[String : Float],比如:
guard let dataRatesDouble = json?["data"] as? [String : Double] else { return } let dataRatesFloat = dataRatesDouble.mapValues { Float($0) }
不过要注意:如果JSON里的数字超出了Float的精度范围,转换后会丢失精度,所以优先推荐直接用Double来适配JSON解析的默认行为。
内容的提问来源于stack exchange,提问作者Phantom59

