如何程序化解码含数量可变重复键的JSON?替代枚举字段方案
更优的JSON解码方案:程序化处理strIngredientN字段
完全不用在模型里硬编码20个可选字段,利用Swift的Codable协议自定义解码逻辑,就能程序化提取所有strIngredient1到strIngredient20的有效值,直接存成一个数组,代码更简洁易维护。
实现思路
- 模型里只需要一个存储配料的数组字段,替代原来20个零散的可选属性
- 自定义
init(from decoder: Decoder)方法,循环遍历1到20的数字,动态拼接键名(比如strIngredient1、strIngredient2...) - 尝试解码每个键对应的字符串,过滤掉空值或
nil的条目,最终收集所有有效配料
示例代码
struct Meal: Codable { // 其他字段比如strMeal、strDrinkAlternate等按需定义 let ingredients: [String] init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: DynamicCodingKey.self) var ingredients = [String]() // 遍历1到20的配料键 for index in 1...20 { let key = DynamicCodingKey(stringValue: "strIngredient\(index)")! // 尝试解码,忽略解码失败的情况(比如字段不存在或值为空) if let ingredient = try? container.decode(String.self, forKey: key), !ingredient.isEmpty { ingredients.append(ingredient) } } self.ingredients = ingredients } } // 自定义编码键,用于动态生成键名 private struct DynamicCodingKey: CodingKey { let stringValue: String init?(stringValue: String) { self.stringValue = stringValue } var intValue: Int? init?(intValue: Int) { return nil } }
代码说明
DynamicCodingKey是自定义的编码键类型,支持通过字符串动态创建键,适配API里的动态命名规则- 解码时循环1到20,逐个尝试解码对应键的字符串,只保留非空的有效配料
- 模型结构更简洁,不用维护20个重复的可选字段,后续如果API调整配料数量(比如扩展到25个),只需要修改循环的范围即可
额外优化
如果需要同时搭配配料的用量(比如strMeasure1到strMeasure20),可以用同样的逻辑提取用量数组,然后和配料数组配对成元组数组:
struct Meal: Codable { let ingredients: [(name: String, measure: String)] init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: DynamicCodingKey.self) var ingredients = [(String, String)]() for index in 1...20 { let ingredientKey = DynamicCodingKey(stringValue: "strIngredient\(index)")! let measureKey = DynamicCodingKey(stringValue: "strMeasure\(index)")! guard let ingredient = try? container.decode(String.self, forKey: ingredientKey), !ingredient.isEmpty, let measure = try? container.decode(String.self, forKey: measureKey), !measure.isEmpty else { continue } ingredients.append((ingredient, measure)) } self.ingredients = ingredients } }
内容的提问来源于stack exchange,提问作者Papi
相关产品推荐
相关产品推荐

