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

Swift中如何解析未在CodingKeys定义的colorX格式JSON字段

解决方法

要将JSON中color1到color10(可能为空字符串)的字段解析到colors数组中,你可以通过访问解码器的完整键值容器,结合动态CodingKey来实现。以下是具体的代码实现:

完整代码实现

struct Cat: Decodable {
    let name: String
    let colors: [String]

    private enum CodingKeys: String, CodingKey {
        case name = "jsonName"
    }

    init(from decoder: Decoder) throws {
        // 解析固定的name字段
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        
        // 获取JSON的完整键值容器,支持访问所有字段
        let fullContainer = try decoder.container(keyedBy: DynamicKey.self)
        
        var tempColors: [String] = []
        // 循环处理color1到color10
        for index in 1...10 {
            let colorKey = DynamicKey(stringValue: "color\(index)")!
            // 尝试解析字段:不存在或为空字符串则跳过
            if let colorValue = try fullContainer.decodeIfPresent(String.self, forKey: colorKey),
               !colorValue.isEmpty {
                tempColors.append(colorValue)
            }
        }
        
        colors = tempColors
    }
}

// 自定义动态CodingKey,匹配任意字符串类型的键
private struct DynamicKey: CodingKey {
    let stringValue: String
    init?(stringValue: String) {
        self.stringValue = stringValue
    }
    
    let intValue: Int?
    init?(intValue: Int) {
        self.intValue = intValue
        self.stringValue = "\(intValue)"
    }
}

关键逻辑说明

  • DynamicKey结构体:实现CodingKey协议,允许我们使用任意字符串作为键来访问JSON字段,完美适配color1、color2这类动态命名的字段。
  • 完整容器访问:通过decoder.container(keyedBy: DynamicKey.self)获取整个JSON的键值容器,突破了CodingKeys仅能访问指定字段的限制。
  • 循环解析与过滤:遍历1到10的索引,构造对应的colorX键,用decodeIfPresent安全解析——如果字段不存在,或者解析出空字符串,直接跳过;有效内容则加入数组。

灵活扩展方案(可选)

如果JSON中的color字段数量不固定(可能多于或少于10个),可以通过筛选所有以color开头的键来实现,同时注意按数字排序避免顺序混乱:

// 替换循环部分的代码
let allColorKeys = fullContainer.allKeys.filter { $0.stringValue.hasPrefix("color") }
// 按color后的数字排序,确保color2在color10前面
let sortedKeys = allColorKeys.sorted {
    guard let num1 = Int($0.stringValue.replacingOccurrences(of: "color", with: "")),
          let num2 = Int($1.stringValue.replacingOccurrences(of: "color", with: "")) else {
        return false
    }
    return num1 < num2
}

for key in sortedKeys {
    if let colorValue = try fullContainer.decodeIfPresent(String.self, forKey: key),
       !colorValue.isEmpty {
        tempColors.append(colorValue)
    }
}

内容的提问来源于stack exchange,提问作者alex17

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 15:43:12