如何解码含嵌套数组的字典并解决Swift Decodable类型赋值报错
问题原因
报错本质是类型不匹配:你声明的searchResults是[String: AnyObject]字典类型,但JSONDecoder()解码后输出的是你自定义的SearchResults结构体类型,二者无法直接赋值。
推荐解决方案(利用Codable类型安全特性)
你已经定义了符合Decodable协议的结构体,完全不需要使用无类型校验的[String: AnyObject]字典存储结果,直接修改searchResults的类型即可:
// 修改变量声明为可选的SearchResults类型,初始值为nil,请求成功后再赋值 var searchResults: SearchResults?
注意你还需要补充定义Verse结构体,保证字段和接口返回匹配:
struct Verse: Decodable { let id: Int let bookName: String let bookId: Int let chapterNumber: Int let verse: String let verseNumber: Int let chapter: Int // 方案1:自定义CodingKeys映射接口的蛇形命名字段 enum CodingKeys: String, CodingKey { case id case bookName = "book_name" case bookId = "book_id" case chapterNumber = "chapter_number" case verse case verseNumber = "verse_number" case chapter } } struct SearchResults: Decodable { let count: Int let next: String? let previous: String? let results: [Verse] }
如果你不想写CodingKeys,也可以在解码时设置自动转换蛇形命名为驼峰命名:
let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase let response = try decoder.decode(SearchResults.self, from: safeData) DispatchQueue.main.async { self.searchResults = response }
可选方案:强行转成[String: AnyObject](不推荐)
如果业务场景确实需要字典类型,可以将解码后的结构体重新序列化再转字典,但会丢失Codable的类型安全优势,还有额外性能损耗,非必要不使用:
// 新增Encodable扩展实现结构体转字典 extension Encodable { func toDictionary() throws -> [String: AnyObject] { let data = try JSONEncoder().encode(self) guard let dict = try JSONSerialization.jsonObject(with: data) as? [String: AnyObject] else { throw NSError(domain: "ConvertError", code: -1, userInfo: [NSLocalizedDescriptionKey: "转换失败"]) } return dict } } // 赋值时调用转换方法 DispatchQueue.main.async { do { self.searchResults = try response.toDictionary() } catch { print(error.localizedDescription) } }
内容的提问来源于stack exchange,提问作者erikvm
相关产品推荐
相关产品推荐

