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

Swift教程:如何将数组中的字符串数值转换为Float类型

解决API返回字符串类型数值转Float的问题

一、推荐方案:用模型类实现类型安全解析

直接用Any和NSDictionary处理JSON很容易出现类型崩溃,建议先定义一个对应课程数据的模型结构体,在解析阶段就完成字符串到Float的转换,同时处理空字符串的情况:

struct Course: Codable {
    let name: String
    let grade: Float? // 空字符串转成nil
    let weight: Float?
    let credits: Float?
    let lastUpdated: String?
    let assignments: [Any]
    
    // 映射JSON里的"Last Updated"字段
    enum CodingKeys: String, CodingKey {
        case name, grade, weight, credits, assignments
        case lastUpdated = "Last Updated"
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        
        // 处理grade:空字符串返回nil,否则转Float
        let gradeStr = try container.decodeIfPresent(String.self, forKey: .grade) ?? ""
        grade = gradeStr.isEmpty ? nil : Float(gradeStr)
        
        // 处理weight
        let weightStr = try container.decodeIfPresent(String.self, forKey: .weight) ?? ""
        weight = weightStr.isEmpty ? nil : Float(weightStr)
        
        // 处理credits
        let creditsStr = try container.decodeIfPresent(String.self, forKey: .credits) ?? ""
        credits = creditsStr.isEmpty ? nil : Float(creditsStr)
        
        lastUpdated = try container.decodeIfPresent(String.self, forKey: .lastUpdated)
        assignments = try container.decodeIfPresent([Any].self, forKey: .assignments) ?? []
    }
}

接着修改getData函数,用JSONDecoder直接解析成模型数组,让completion返回类型安全的[Course]:

func getData(_ completion: @escaping ([Course]) -> ()) {
    let urlPath = "https://gradual-deploy.vercel.app/students/currentclasses?username=john&password=doe"
    
    guard let url = URL(string: urlPath) else {
        completion([])
        return
    }
    
    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
        guard let data = data else {
            completion([])
            return
        }
        do {
            // API返回的是外层数组包裹字典,先解析外层结构
            let outerArray = try JSONDecoder().decode([[String: [Course]]].self, from: data)
            let currentClasses = outerArray.first?["currentClasses"] ?? []
            completion(currentClasses)
        } catch {
            print("解析失败:\(error)")
            completion([])
        }
    }
    task.resume()
}

之后在闭包里就能直接用转换好的Float值:

getData { courses in
    for course in courses {
        print("课程:\(course.name)")
        if let grade = course.grade {
            print("成绩:\(grade)")
        } else {
            print("暂无成绩")
        }
        print("权重:\(course.weight ?? 0)")
        print("学分:\(course.credits ?? 0)")
    }
}

二、快捷方案:直接在闭包中转换

如果不想修改原函数结构,也可以在闭包里逐个处理字典中的字符串:

getData { studentData in
    for item in studentData {
        guard let courseDict = item as? [String: Any] else { continue }
        
        // 转换grade
        let gradeStr = courseDict["grade"] as? String ?? ""
        let grade = gradeStr.isEmpty ? nil : Float(gradeStr)
        
        // 转换weight
        let weightStr = courseDict["weight"] as? String ?? ""
        let weight = weightStr.isEmpty ? nil : Float(weightStr)
        
        // 转换credits
        let creditsStr = courseDict["credits"] as? String ?? ""
        let credits = creditsStr.isEmpty ? nil : Float(creditsStr)
        
        // 使用转换后的值
        print("课程名:\(courseDict["name"] ?? "未知")")
        print("成绩:\(grade ?? 0)") // 空值可以用默认0,或者按需处理
    }
}

注意点

  • 空字符串直接转Float会返回nil,必须先判断字符串是否为空
  • 如果字符串是非法数字(比如"abc"),Float()也会返回nil,根据业务需求可以设置默认值或者跳过该数据
  • 优先用模型类方案,代码更易维护,还能避免强制类型转换导致的崩溃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 09:06:35