Swift如何将三种不同结构的JSON解码为统一格式
Swift Decodable 多结构统一解码实现方案
核心实现代码
首先定义统一的响应结构,兼容三类API返回格式:
import Foundation // 核心曲目模型,和三类接口返回的曲目字段完全对齐 struct Track: Decodable { // 按需定义你的曲目字段,比如id、name、artist等 let id: String let name: String let artist: String } // 统一输出的响应结构 struct TracksResponse: Decodable { let tracks: [Track] // 中间辅助结构体,用于第三种嵌套结构解析 private struct TrackItemWrapper: Decodable { let track: Track } private enum CodingKeys: String, CodingKey { case tracks, items } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 第一种情况:根节点直接有tracks数组 if let tracks = try? container.decode([Track].self, forKey: .tracks) { self.tracks = tracks return } // 第二种情况:根节点items字段直接存曲目数组 if let directItems = try? container.decode([Track].self, forKey: .items) { self.tracks = directItems return } // 第三种情况:根节点items字段是嵌套track的对象数组 let wrappedItems = try container.decode([TrackItemWrapper].self, forKey: .items) self.tracks = wrappedItems.map(\.track) } }
报错原因说明
你之前遇到的Expected to decode Dictionary<String, Any> but found an array instead.报错,是因为解码第三种结构时,错误地将根节点下的items字段声明为字典类型,实际上items本身是数组,数组内的单个元素才是包含track字段的字典,上述代码通过中间结构体TrackItemWrapper先解析数组,再提取内部track字段即可解决问题。
Alamofire 调用示例
直接使用定义好的TracksResponse作为解码类型即可,无需额外处理:
AF.request("你的API地址").responseDecodable(of: TracksResponse.self) { response in switch response.result { case .success(let res): print("统一拿到的曲目数组:\(res.tracks)") case .failure(let error): print("请求或解码失败:\(error)") } }
兼容的三类JSON结构示例
- 第一类返回格式
{ "tracks": [ {"id": "1", "name": "曲目1", "artist": "歌手1"} ] }
- 第二类返回格式
{ "items": [ {"id": "1", "name": "曲目1", "artist": "歌手1"} ] }
- 第三类返回格式
{ "items": [ {"track": {"id": "1", "name": "曲目1", "artist": "歌手1"}} ] }
内容的提问来源于stack exchange,提问作者Gabriel D M
相关产品推荐
相关产品推荐

