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

Swift如何正确读取本地JSON文件并赋值给Codable结构体?

本地JSON与Codable结构体映射实现方案

问题核心原因

  • 现有代码中使用的JSONSerialization仅能将JSON数据转换为Foundation基础类型(字典/数组/字符串/数字等),无法自动完成与自定义结构体的映射,需要使用JSONDecoder完成Codable类型的解码
  • 定义的结构体属性名与JSON实际的key不匹配,必须手动声明CodingKeys建立映射关系,否则解码器无法找到对应字段会直接抛出错误
  • 外层Countries结构体仅在JSON根节点为{"results": [国家数组]}格式时才需要使用,从现有代码逻辑判断,当前JSON根节点是数组类型,不需要套这层结构。

第一步:修正结构体定义,添加映射关系

struct Country: Codable {
    var aNumber: Int
    var cName: String
    var population: Int
    var landArea: Int
    var density: Int
    var facts: String
    
    // 枚举case对应结构体属性名,rawValue对应JSON里的实际key
    enum CodingKeys: String, CodingKey {
        case aNumber = "#"
        case cName = "Country"
        case population = "Population\n(2020)"
        case landArea = "Land Area\n(Km²)"
        case density = "Density\n(P/Km²)"
        case facts = "FACTS"
    }
}

// 仅当JSON根结构为带results字段的字典时保留,根节点为数组可直接删除
struct Countries: Codable {
    var results: [Country]
}

第二步:替换读取逻辑,使用JSONDecoder解码

直接丢弃JSONSerialization相关逻辑,用解码器直接把Data转成目标类型:

private func readJson() {
    do {
        guard let fileURL = Bundle.main.url(forResource: "csvjson", withExtension: "json") else {
            print("本地JSON文件不存在,请检查文件是否加入项目Target")
            return
        }
        let jsonData = try Data(contentsOf: fileURL)
        let decoder = JSONDecoder()
        
        // 根据JSON实际根结构二选一:
        // 1. 根节点为数组(现有代码判断走了数组分支,用这行即可)
        let countryList = try decoder.decode([Country].self, from: jsonData)
        print("解析完成,共加载\(countryList.count)条国家数据")
        
        // 2. 根节点为带results的字典时,注释上面两行,用下面的代码
        // let result = try decoder.decode(Countries.self, from: jsonData)
        // let countryList = result.results

    } catch {
        // 直接打印error对象,会明确指出缺失字段、类型不匹配等具体错误原因
        print("JSON解析失败:\(error)")
    }
}

排查注意事项

  • 不要用error.localizedDescription获取解码错误,本地化描述只会显示笼统的“数据损坏”信息,直接打印error对象可以拿到精准到字段的错误提示,排查效率高很多
  • 确保本地JSON文件格式合法,提供的JSON示例缺少结尾的闭合},实际文件要补全格式,否则会解码失败
  • 选中本地JSON文件,在右侧File Inspector的Target Membership里勾选当前项目target,否则Bundle无法找到文件
  • 如果后续JSON的key有变更,只需要修改CodingKeys里对应的rawValue即可,不需要修改业务层使用的结构体属性名

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 22:36:21