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
相关产品推荐
相关产品推荐

