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

Swift 4解析JSON时保留Double小数格式并判断原始数字类型

解决Swift中JSONSerialization解析数字类型模糊的问题

嘿,这个问题我之前踩过坑——JSONSerialization解析JSON时,会把所有数字都包装成NSNumber实例,而NSNumber本身支持双向转换(Int和Double互转),所以判断顺序一变结果就不对,确实很难直接区分JSON里的原始是整数还是小数。下面给你几个可行的解决思路:

思路1:用Codable明确指定类型(推荐)

如果你的JSON结构是固定的,优先用JSONDecoder结合自定义Codable类型,这样能直接在定义阶段就锁定数字类型,从根源上避免模糊判断:

// 假设你的JSON结构是 {"value": 1.0}
struct MyModel: Codable {
    let value: Double // 如果原始JSON是整数1,就改成Int
}

do {
    let model = try JSONDecoder().decode(MyModel.self, from: data)
    // 这里model.value的类型完全匹配你定义的,完美保留原始格式意图
} catch {
    print("解析失败:\(error)")
}

这种方式最安全,也符合Swift的类型安全原则,只要JSON结构固定就优先用它。

思路2:结合原始JSON字符串检查(原生方案)

如果必须用JSONSerialization,可以先把原始Data转成字符串,再定位到对应数字的字符串片段,通过是否包含小数点来判断原始类型:

do {
    // 先获取原始JSON字符串
    guard let jsonString = String(data: data, encoding: .utf8) else {
        print("无法转成字符串")
        return
    }
    // 解析成Any类型
    let json = try JSONSerialization.jsonObject(with: data, options: [])
    
    // 假设我们要检查key为"number"的值
    if let dict = json as? [String: Any], let num = dict["number"] as? NSNumber {
        // 这里用正则匹配提取对应数字的字符串片段
        let regexPattern = "\"number\":\\s*([0-9]+(\\.[0-9]+)?)"
        if let regex = try? NSRegularExpression(pattern: regexPattern),
           let match = regex.firstMatch(in: jsonString, range: NSRange(jsonString.startIndex..., in: jsonString)) {
            let numString = String(jsonString[Range(match.range(at: 1), in: jsonString)!])
            if numString.contains(".") {
                print("原始是小数类型:\(num)")
            } else {
                print("原始是整数类型:\(num)")
            }
        }
    }
} catch {
    print(error)
}

这个方法有点繁琐,但完全用原生API实现,适合不能引入第三方库的场景。

思路3:用第三方JSON库(简单高效)

像SwiftyJSON这类第三方库会在解析时保留原始JSON的类型信息,能直接区分整数和小数:

import SwiftyJSON

let json = JSON(data: data)
if let doubleValue = json["number"].double {
    print("原始是小数类型:\(doubleValue)")
} else if let intValue = json["number"].int {
    print("原始是整数类型:\(intValue)")
}

SwiftyJSON内部会记录每个值的原始JSON类型,所以不用操心转换顺序的问题,用起来非常省心。

补充:为什么检查CFType没用?

因为不管JSON里是1还是1.0,JSONSerialization都会把它转成NSNumber,而NSNumber的CFType都是CFNumberType,所以通过CFType根本区分不出原始类型,这也是这个思路行不通的原因。

内容的提问来源于stack exchange,提问作者swebal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:49:53