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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 09:45:04