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

Swift中如何为无键嵌套数组创建Decodable解析模型?

解析无键嵌套数组JSON的正确实现(Swift + Alamofire 5.6.2)

你的当前代码无法解析的核心问题是:目标JSON是数组嵌套数组的结构,每个子数组包含固定顺序的不同类型元素(字符串、整数、浮点数),而你定义的Item结构体默认会按键值对解析,完全匹配不上这种无键数组格式。

方案一:自定义Item的Codable实现(推荐,适合固定结构的子数组)

不需要用枚举,直接给Item自定义解码/编码逻辑,按数组索引顺序读取元素即可:

struct Item: Codable {
    let name: String
    let integerValue: Int
    let doubleValue: Double
    
    // 自定义解码逻辑,适配无键数组
    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        // 严格按JSON子数组的顺序解析元素
        name = try container.decode(String.self)
        integerValue = try container.decode(Int.self)
        doubleValue = try container.decode(Double.self)
    }
    
    // 如果需要编码,同样按数组顺序输出
    func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        try container.encode(name)
        try container.encode(integerValue)
        try container.encode(doubleValue)
    }
}

然后修改Alamofire请求代码,指定解析类型为[Item].self:

AF.request("https://xxx.json").validate().responseDecodable(of: [Item].self) { response in
    switch response.result {
    case .success(let items):
        // 处理解析后的Item数组
        items.forEach { item in
            print("名称:\(item.name),整数:\(item.integerValue),浮点数:\(item.doubleValue)")
        }
    case .failure(let error):
        print("解析失败:\(error.localizedDescription)")
    }
}

方案二:用枚举处理异构元素(适合子数组元素类型不固定的场景)

如果你的JSON子数组元素类型可能不固定(比如偶尔出现其他类型),可以用枚举来封装不同类型的元素,再手动组装成Item:

enum ArrayElement: Codable {
    case string(String)
    case int(Int)
    case double(Double)
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        // 依次尝试解析不同类型
        if let stringVal = try? container.decode(String.self) {
            self = .string(stringVal)
        } else if let intVal = try? container.decode(Int.self) {
            self = .int(intVal)
        } else if let doubleVal = try? container.decode(Double.self) {
            self = .double(doubleVal)
        } else {
            throw DecodingError.dataCorruptedError(in: container, debugDescription: "不支持的元素类型")
        }
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .string(let val): try container.encode(val)
        case .int(let val): try container.encode(val)
        case .double(let val): try container.encode(val)
        }
    }
}

解析时先拿到嵌套数组,再转换为Item:

AF.request("https://xxx.json").validate().responseDecodable(of: [[ArrayElement]].self) { response in
    switch response.result {
    case .success(let arrayArrays):
        let items = arrayArrays.compactMap { elements -> Item? in
            guard case .string(let name) = elements[0],
                  case .int(let intVal) = elements[1],
                  case .double(let doubleVal) = elements[2] else {
                return nil
            }
            return Item(name: name, integerValue: intVal, doubleValue: doubleVal)
        }
        // 处理转换后的items
    case .failure(let error):
        print("解析失败:\(error)")
    }
}

总结

你的场景中子数组结构固定,方案一足够简洁高效,不需要用枚举;如果后续有元素类型变动的需求,再考虑方案二的枚举实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 16:30:17