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

Swift使用Codable解析JSON报错,求教Any类型字典解析方法

在Swift中解析GitHub API JSON时的Any类型处理问题

先说说你遇到的那个报错:Could not cast value of type '__NSDictionaryI' to 'NSData',这问题其实很明确——你多做了一步没必要的操作:先用JSONSerialization把原始Data转成了字典类型的对象,然后又想把这个字典强制转成Data给JSONDecoder解析,这肯定会失败啊!JSONDecoder是直接解析网络请求返回的原始Data的,完全不需要先转成Any类型的中间对象~

除此之外,你的结构体定义也和GitHub API的实际返回结构不匹配,这也是后续解析会出问题的关键,我帮你一步步修正:

第一步:匹配API的实际返回结构

GitHub搜索仓库的API返回的顶层结构是一个包含items数组的对象,每个item是一个仓库信息,里面包含full_name、html_url(仓库的地址),还有owner子对象,followers_url是owner里的属性。所以我们需要调整结构体:

// 顶层响应结构体,对应API返回的整个JSON
struct SearchResponse: Decodable {
    let items: [Repository]
}

// 仓库信息结构体
struct Repository: Decodable {
    let full_name: String
    let html_url: String
    let owner: Owner
}

// 仓库所有者结构体
struct Owner: Decodable {
    let followers_url: String
}

第二步:修正JSON解析逻辑

去掉多余的JSONSerialization步骤,直接用JSONDecoder解析原始的Data,同时不要用try!(会导致崩溃),用do-catch妥善处理错误:

enum JSONError: String, Error {
    case noData = "ERROR: no data"
    case conversionFailed = "ERROR: conversion from JSON failed"
}

func jsonParser() {
    let urlPath = "https://api.github.com/search/repositories?q=language:ruby&sort=stars&order=desc"
    guard let endpoint = URL(string: urlPath) else {
        print("Error creating endpoint")
        return
    }
    // 不需要用NSMutableURLRequest,直接用URLRequest就行
    let request = URLRequest(url: endpoint)
    
    URLSession.shared.dataTask(with: request) { (data, response, error) in
        do {
            guard let data = data else {
                throw JSONError.noData
            }
            // 直接用JSONDecoder解析原始Data
            let searchResponse = try JSONDecoder().decode(SearchResponse.self, from: data)
            
            // 遍历仓库信息,获取你需要的字段
            for repo in searchResponse.items {
                print("仓库全名: \(repo.full_name)")
                print("仓库地址: \(repo.html_url)")
                print("所有者粉丝地址: \(repo.owner.followers_url)")
                print("---")
            }
        } catch let error as JSONError {
            print(error.rawValue)
        } catch {
            print("解析错误: \(error.localizedDescription)")
        }
    }.resume()
}

第三步:解释关键改动

  • 移除了JSONSerialization的步骤:直接用JSONDecoder解析网络返回的原始Data,避免了Any类型的转换问题
  • 调整结构体层级:完全匹配GitHub API的返回结构,确保解析时能正确映射字段
  • 替换NSMutableURLRequest为URLRequest:Swift里更推荐用原生的URLRequest,不需要用OC的可变类型
  • 去掉try!改用try配合do-catch:避免解析失败时直接崩溃,能捕获并处理错误

这样修改之后,你就能正确获取到想要的full_name、html_url和followers_url信息啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:26:05