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

Swift POST请求JSON解析失败,Codable使用问题求助

问题解决:Swift JSON解析崩溃修复与数据保存

你崩溃的核心原因是结构体里的data类型和API返回的JSON不匹配:API返回的data是单个对象({...}),但你定义成了数组[LoginUserData]?,类型不匹配直接导致解码失败崩溃。以下是完整的修复方案:

1. 修正Codable结构体

把LoginUser里的data类型从数组改成单个对象,同时建议用let定义属性(API返回数据一般无需修改):

struct LoginUser: Codable {
    let error: Bool
    let data: LoginUserData?
    let message: String
}

struct LoginUserData: Codable {
    let name: String
    let age: Int
    let active: Bool
}

2. 修复解析代码

你已经创建了JSONDecoder但没用到,替换原来的JSONSerialization,改用解码器直接解析到结构体,同时完善错误处理:

func loginCall() {
    guard let url = URL(string: "http://192.168.0.50/api/v1/?op=ilogin") else {
        return
    }
    var request = URLRequest(url: url)
    
    request.httpMethod = "POST"
    // 新增:添加表单数据的Content-Type头,确保API正确解析请求体
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    
    let body = "email=myemail@gmail.com&password=jdsdsdsdf&ver=0.1"
    request.httpBody = body.data(using: .utf8)
    
    let session = URLSession.shared
    let dataTask = session.dataTask(with: request) { data, response, error in
        // 先处理请求错误
        if let error = error {
            print("请求出错:\(error.localizedDescription)")
            return
        }
        
        guard let responseData = data else {
            print("未获取到响应数据")
            return
        }
        
        let decoder = JSONDecoder()
        do {
            // 解码到LoginUser结构体
            let loginResult = try decoder.decode(LoginUser.self, from: responseData)
            print("登录结果:\(loginResult.message)")
            
            // 打印用户信息(处理可选值,避免崩溃)
            if let userData = loginResult.data {
                print("用户名:\(userData.name),年龄:\(userData.age),状态:\(userData.active ? "活跃" : "非活跃")")
                
                // 保存数据到UserDefaults(适合小体量数据)
                if let encodedData = try? JSONEncoder().encode(loginResult) {
                    UserDefaults.standard.set(encodedData, forKey: "SavedLoginUser")
                }
            }
            
        } catch {
            print("解码失败:\(error.localizedDescription)")
            // 打印详细错误信息,方便调试
            print("错误详情:\(error)")
        }
    }
    dataTask.resume()
}

3. 读取保存的数据

如果需要从UserDefaults读取之前保存的登录信息,可以用以下代码:

func getSavedLoginUser() -> LoginUser? {
    guard let savedData = UserDefaults.standard.data(forKey: "SavedLoginUser") else {
        return nil
    }
    do {
        return try JSONDecoder().decode(LoginUser.self, from: savedData)
    } catch {
        print("读取保存数据失败:\(error)")
        return nil
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:10:31