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

向启用JWT鉴权的API发起GET请求时JSON数据解码失败

问题说明
  • 对接开启JWT鉴权的项目列表GET接口时,返回的字节数据无法解码为预期的Project对象数组
  • 业务逻辑:用户登录后点击按钮,携带接口返回的JWT令牌发起请求拉取项目数据,用于跳转项目列表页面
  • 现有网络请求实现:
func getUserProject(token: String, completion: @escaping (Result<[Project], NetworkError>) -> Void) {
    
    guard let url = URL(string: "https://api.t.io/api/manage/user/projects?archived=false&logic=and&page=0&size=10") else {
        completion(.failure(.invalidURL))
        print("unable to connect URL🆘")
        return
    }
    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
  let task =  URLSession.shared.dataTask(with: request) { (data, response, error) in
        guard let data = data, error == nil else {
            completion(.failure(.noData))
            print("Bad🥺")
            return
        }
        guard let Projects = try? JSONDecoder().decode([Project].self, from: data) else {
            completion(.failure(.decodingError))
            print(data)
            print("Error Decoding Data🥵")
            return
        }
        completion(.success(Projects))
    }
        task.resume()
}
  • 运行触发解码错误,错误日志截图:
    错误日志截图
  • 当前定义的Project模型代码:
struct Project: Codable {
    let createdBy: String
    let createdDate: EdDate
    let lastModifiedBy: String
    let lastModifiedDate: EdDate
    let id: Int
    let name: String
    let customID: JSONNull?
    let shared: Bool
    let salt: JSONNull?
    let isCOMRequestAutomatic: Bool
    let client: Client
    let company: Company
    let projectKeywords: [JSONAny]
    let projectStartDate, projectEndDate: JSONNull?

    enum CodingKeys: String, CodingKey {
        case createdBy, createdDate, lastModifiedBy, lastModifiedDate, id, name, status
        case imageURL
        case customID
        case shared, salt
        case isCOMRequestAutomatic
        case client, company, projectKeywords, projectStartDate, projectEndDate
    }
}
问题排查&修复方案
  1. 先确认接口真实返回结构
    当前直接打印data只能看到原始字节,无法确认JSON结构,先把data转成UTF8字符串打印,确认返回格式:

    // 在拿到data后、解码前加这段代码
    if let rawJson = String(data: data, encoding: .utf8) {
        print("接口原始返回:\(rawJson)")
    }
    

    带分页参数的接口绝大多数不会直接返回数组,一般会带通用响应外层包装,比如返回结构为{ "code": 200, "msg": "success", "data": { "list": [/* 项目数组 */], "total": 100 } },这种情况直接解码[Project].self必然失败,需要根据真实返回结构编写对应的外层响应模型,从嵌套字段中取项目数组再解码。

  2. 修正模型CodingKeys和属性的映射关系
    当前CodingKeys中枚举了status、imageURL两个键,但是Project结构体中没有定义这两个对应的属性,一旦接口返回这两个字段,会直接触发解码失败;如果接口不返回这两个字段,CodingKeys中声明了非可选的缺失字段也会报错。要么补全这两个字段的属性定义,要么把CodingKeys中多余的键删除,保证所有枚举的CodingKey都有对应属性,所有需要解码的属性都有匹配的CodingKey映射。

  3. 捕获具体解码错误,不要用try?吞掉异常
    当前用try?强制解包解码结果,一旦失败看不到任何具体错误信息,把解码逻辑替换为do-catch写法,拿到系统抛出的具体错误,可以直接定位到是字段类型不匹配、字段缺失还是嵌套模型解析失败:

    do {
        // 注意如果接口有外层包装,这里要解码对应的外层响应模型,不是直接解[Project]
        let projectList = try JSONDecoder().decode([Project].self, from: data)
        completion(.success(projectList))
    } catch {
        // 这里会打印精确到字段的错误信息,比如"No value associated with key CodingKeys(stringValue: "status", intValue: nil)"
        print("解码失败详情:\(error)")
        completion(.failure(.decodingError))
    }
    
  4. 检查嵌套类型的Codable实现
    确认模型中用到的EdDate、Client、Company、JSONNull、JSONAny所有自定义类型都正确实现了Codable协议,任意一个嵌套类型不满足Codable要求,都会导致整个Project模型解码失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:03:20