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

如何程序化解码含数量可变重复键的JSON?替代枚举字段方案

更优的JSON解码方案:程序化处理strIngredientN字段

完全不用在模型里硬编码20个可选字段,利用Swift的Codable协议自定义解码逻辑,就能程序化提取所有strIngredient1到strIngredient20的有效值,直接存成一个数组,代码更简洁易维护。

实现思路

  1. 模型里只需要一个存储配料的数组字段,替代原来20个零散的可选属性
  2. 自定义init(from decoder: Decoder)方法,循环遍历1到20的数字,动态拼接键名(比如strIngredient1、strIngredient2...)
  3. 尝试解码每个键对应的字符串,过滤掉空值或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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 08:06:21