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

Swift使用Codable解析含动态Key的restcountries接口JSON方案

Swift 解析restcountries接口动态键nativeName字段方案

核心问题原因

原实现将nativeName定义为带固定deu属性的结构体,仅能匹配返回中包含deu键的场景,无法适配接口根据国家语言动态返回不同键名的结构。由于所有nativeName下动态键对应的值结构完全一致(均包含common、official两个字符串字段),直接用字符串键的字典类型承接即可实现动态适配。

修正后实现代码

1. 数据模型修正

// 国家主数据模型
struct Country: Codable {
    let name: Name
    let cca2: String
    let flag: String
}

struct Name: Codable {
    let common, official: String
    // 核心调整:动态键字段用[String: 通用值模型]字典承接,兼容任意语言代码键
    let nativeName: [String: NativeLanguageEntry]?
}

// 通用本地语言条目模型,所有动态键对应的值均符合该结构
struct NativeLanguageEntry: Codable {
    let official, common: String?
}

2. 解析服务修正

class ParsingService {
    
    static let shared = ParsingService()
    
    func fetchData() {
        guard let url = URL(string: "https://restcountries.com/v3.1/all") else {
            print("DEBUG: URL无效")
            return
        }
        
        let task = URLSession.shared.dataTask(with: url) { data, _, error in
            guard let retrievedData = data, error == nil else {
                print("DEBUG: 数据拉取失败: \(error?.localizedDescription ?? "未知错误")")
                return
            }

            guard let decodedData = self.parseJSON(inputData: retrievedData) else {
                print("DEBUG: 数据解析失败")
                return
            }
            
            // 测试取值示例
            guard let firstCountry = decodedData.first else { return }
            print("国家二字码: \(firstCountry.cca2)")
            print("国旗标识: \(firstCountry.flag)")
            
            // 动态取值方式1:取返回的第一个本地语言条目
            if let firstEntry = firstCountry.name.nativeName?.first {
                print("首个本地语言(代码:\(firstEntry.key))官方名:\(firstEntry.value.official ?? "无数据")")
            }
            
            // 动态取值方式2:按指定语言代码查询,例如查询英语条目
            if let engEntry = firstCountry.name.nativeName?["eng"] {
                print("英语本地通用名:\(engEntry.common ?? "无数据")")
            }
            
            // 动态取值方式3:遍历所有本地语言条目
            firstCountry.name.nativeName?.forEach { langCode, entry in
                print("语言代码:\(langCode),通用名:\(entry.common ?? "无数据"),官方名:\(entry.official ?? "无数据")")
            }

            DispatchQueue.main.async {
                // 主线程UI更新逻辑
            }
        }
        task.resume()
    }
    
    func parseJSON(inputData: Data) -> [Country]? {
        let decoder = JSONDecoder()
        do {
            // 移除原代码的try?,避免吞掉解析错误,方便排查问题
            let data = try decoder.decode([Country].self, from: inputData)
            return data
        } catch {
            print("DEBUG: 解析错误详情: \(error)")
            return nil
        }
    }
}

关键修改点

  • 移除原实现中写死deu属性的NativeName结构体,将nativeName字段类型改为可选字典[String: NativeLanguageEntry]?,自动适配接口返回的任意动态语言键
  • 修正原解析方法中try?吞错误的问题,解析失败时输出完整错误信息,降低调试成本
  • 提供三种常用动态取值逻辑,覆盖不同业务场景下的nativeName读取需求
  • 修正原代码中的拼写错误(nill改为nil),优化模型命名语义,避免歧义

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:00:57