如何修复Swift中JSON转换时的Coding Keys缺失错误
通过ViewModel调用API接口获取数据并转换为数组时,JSON转换持续报错。
ViewModel代码
class ViewModel: ObservableObject { @Published var courses: [Course] = [] func fetch() { guard let url = URL(string: "https://api.spaceflightnewsapi.net/v3/articles") else { return } let task = URLSession.shared.dataTask(with: url) { [weak self]data, _, error in guard let data = data, error == nil else { return } // Convert to JSON do { let courses = try JSONDecoder().decode([Course].self, from: data) DispatchQueue.main.async { self?.courses = courses } } catch { print(error) //---Error Here--- print("Error with converting to JSON") } } task.resume() } }
Course结构体定义
struct Course: Hashable, Codable { let name: String let image: String let id: Int let title: String let newsSite: String let summary: String let publishedAt: String let updatedAt: String let featured: Bool let launches: String let events: String }
报错信息
keyNotFound(CodingKeys(stringValue: "name", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: "name", intValue: nil) ("name").", underlyingError: nil))
请问是否在Course结构体中遗漏了某些配置?
报错核心原因是Course结构体的字段与API返回的JSON结构不匹配,具体问题和修改方案如下:
移除不存在的
name字段
API返回的文章数据里没有name这个键,JSONDecoder找不到对应值就会抛出keyNotFound错误,直接删掉这个字段即可。修正
image字段的键名
API返回的图片字段键是imageUrl,不是你定义的image,需要把结构体里的image改成imageUrl。修正
launches和events的类型
这两个字段在API返回中是数组类型(包含多个对象),不是String。你需要定义对应的子结构体来解析它们,或者如果不需要具体内容,可以用[String: Codable]类型。
修改后的Course结构体及子结构体
struct Course: Hashable, Codable { let id: Int let title: String let newsSite: String let summary: String let publishedAt: String let updatedAt: String let featured: Bool let imageUrl: String // 修正键名 let launches: [Launch] // 改为数组类型 let events: [Event] // 改为数组类型 } // 解析launches数组的子结构体 struct Launch: Hashable, Codable { let id: String let provider: String } // 解析events数组的子结构体 struct Event: Hashable, Codable { let id: String let provider: String }
可选优化
如果不需要解析launches和events的具体内容,也可以把它们定义为[String: Any],但需要手动实现Codable,不如定义子结构体清晰。
修改完成后,重新运行代码,JSON解析就能正常工作了。
内容的提问来源于stack exchange,提问作者Jack

