Swift Recipe App解析本地JSON时Summary字段报Type Mismatch Error的问题
问题核心原因
JSON 中 summary 字段的实际结构是 由多个单键小字典组成的数组,但你在 Recipe 模型中将其定义为单个 [String: String] 字典,类型不匹配直接触发解码错误。
解决方案
根据你的实际使用需求二选一即可:
方案1:最小改动适配JSON原结构
直接修正模型中 summary 的类型定义,改动量最小,修改后立刻可以正常解码、不会崩溃:
// 原错误定义 // var summary: [String:String] // 修改为匹配JSON结构的类型 var summary: [[String: String]]
后续使用时,遍历这个数组就可以取出对应的值,示例:
// 取菜品评分的逻辑 if let ratingItem = recipe.summary.first(where: { $0.keys.contains("rating") }) { let ratingValue = ratingItem["rating"] }
方案2:自定义解码逻辑,实现你最初预期的使用方式
如果你希望解码完成后,可以直接像用普通字典一样通过recipe.summary["对应键"]取值,不需要每次遍历数组,就保留你原本想要的summary: [String:String]类型定义,给Recipe类添加自定义解码逻辑,把数组里的所有小字典合并成一个扁平的大字典即可:
class Recipe: Identifiable, Decodable { var id: UUID? var title: String var image: String var description: String var prepTime: String var cookTime: String var servings: Int var summary: [String: String] // 保留你原本设计的类型 var ingredients: [Ingredient] var directions: [String] // 自定义解码流程 required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 普通属性按原逻辑正常解码 id = try container.decodeIfPresent(UUID.self, forKey: .id) title = try container.decode(String.self, forKey: .title) image = try container.decode(String.self, forKey: .image) description = try container.decode(String.self, forKey: .description) prepTime = try container.decode(String.self, forKey: .prepTime) cookTime = try container.decode(String.self, forKey: .cookTime) servings = try container.decode(Int.self, forKey: .servings) ingredients = try container.decode([Ingredient].self, forKey: .ingredients) directions = try container.decode([String].self, forKey: .directions) // 自定义处理summary字段 // 先把数组形式的原始数据解码出来,再把所有小字典合并成一个大字典 let rawSummaryArray = try container.decode([[String: String]].self, forKey: .summary) var mergedSummary: [String: String] = [:] rawSummaryArray.forEach { smallDict in mergedSummary.merge(smallDict) { (_, new) in new } } summary = mergedSummary } // 对应属性的编码键,无需额外修改 enum CodingKeys: String, CodingKey { case id, title, image, description, prepTime, cookTime, servings, summary, ingredients, directions } }
修改完成后,你可以直接通过下标取值:
let preparationTime = recipe.summary["preparation"] let servingCount = recipe.summary["serves"]
额外注意
你提供的示例JSON里,ingredients数组中“Ground Cinnamon”对应的条目末尾漏了一个逗号,属于JSON语法错误,实际运行解码时也会触发报错,记得补上。
内容的提问来源于stack exchange,提问作者LizG
相关产品推荐
相关产品推荐

