如何扁平化嵌套JSON结构并解决Swift Decodable解码报错问题
嵌套JSON扁平化解码实现
需求
将指定嵌套JSON结构做扁平化处理,提取嵌套字段转换为目标结构。
待处理原始JSON
{ "items": [{ "track": { "name": "Never Gonna Give You Up" } }] }
期望输出结构
{ "tracks": [{ "name": "Never Gonna Give You Up" }] }
原有实现与报错
尝试的代码
struct TrackResponse: Decodable { let tracks: [Track] enum CodingKeys: String, CodingKey { case tracks = "items" } enum TrackKeys: String, CodingKey { case track } init(from decoder: Decoder) throws { let outerContainer = try decoder.container(keyedBy: CodingKeys.self) let trackContainer = try outerContainer.nestedContainer(keyedBy: TrackKeys.self, forKey: .tracks) self.tracks = try trackContainer.decode([Track].self, forKey: .track) } struct Track: Decodable { var name: String } }
报错信息
Expected to decode Dictionary<String, Any> but found an array instead.
解决方案
错误根因
items字段对应的JSON类型是数组,而nestedContainer方法仅能作用于字典类型的容器,直接对数组调用该方法会触发类型不匹配错误。
正确实现
解码时先将items字段解析为数组类型的无键容器,遍历数组内的每个元素,逐个提取嵌套的track字段后拼装为最终的tracks数组即可,实现代码如下:
struct TrackResponse: Decodable { let tracks: [Track] enum CodingKeys: String, CodingKey { case items } enum ItemCodingKeys: String, CodingKey { case track } init(from decoder: Decoder) throws { let outerContainer = try decoder.container(keyedBy: CodingKeys.self) // 解析items为数组类型的无键容器 var itemsContainer = try outerContainer.nestedUnkeyedContainer(forKey: .items) var tracksTemp = [Track]() // 遍历数组所有元素提取track while !itemsContainer.isAtEnd { let itemContainer = try itemsContainer.nestedContainer(keyedBy: ItemCodingKeys.self) let singleTrack = try itemContainer.decode(Track.self, forKey: .track) tracksTemp.append(singleTrack) } self.tracks = tracksTemp } struct Track: Decodable { var name: String } }
内容的提问来源于stack exchange,提问作者Gabriel D M
相关产品推荐
相关产品推荐

