如何处理格式与类型多变的Decodable嵌套数组?
当然可以用Decodable来处理这种多变结构的数组,完全没必要退回到字典!核心思路是用枚举+关联值来封装不同类型的分组数据,让Decodable可以根据group字段的值动态解析对应的data数组,既保留类型安全,又能灵活适配不同结构。
第一步:用枚举封装不同分组类型
先创建一个枚举SearchResultGroup并实现Decodable,用关联值对应不同分组的数据集:
enum SearchResultGroup: Decodable { case movies([SearchDataMovies]) case tvShows([SearchDataTV]) case artists([SearchDataArtists]) // 定义JSON字段对应的编码键 private enum CodingKeys: String, CodingKey { case group, data } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 先解析group字段,判断当前是哪种类型的分组 let group = try container.decode(String.self, forKey: .group) switch group { case "Movies": let movies = try container.decode([SearchDataMovies].self, forKey: .data) self = .movies(movies) case "TV-Shows": let tvShows = try container.decode([SearchDataTV].self, forKey: .data) self = .tvShows(tvShows) case "Artists": let artists = try container.decode([SearchDataArtists].self, forKey: .data) self = .artists(artists) default: // 遇到未知分组类型时抛出错误,也可以根据需求做默认处理 throw DecodingError.dataCorruptedError(forKey: .group, in: container, debugDescription: "Unknown group type: \(group)") } } }
第二步:调整主结构体的类型
把原来SearchData里的data类型改成枚举数组,你之前定义的各个数据结构体可以完全保留:
struct SearchData: Decodable { var success: Bool var server_response_time: Int var data: [SearchResultGroup] // 替换为枚举数组类型 } // 原有数据结构体无需修改 struct SearchDataMovies: Decodable { let title: String let year: String } struct SearchDataTV: Decodable { let title: String let year: Int } struct SearchDataArtists: Decodable { let name: String }
第三步:解码和使用示例
现在就可以正常解码JSON数据,并且通过枚举的switch分支安全处理不同类型的分组:
// 假设jsonData是你获取到的原始JSON数据 do { let searchData = try JSONDecoder().decode(SearchData.self, from: jsonData) // 遍历处理每个分组 for group in searchData.data { switch group { case .movies(let movies): print("🎬 找到电影:\(movies.count)部") movies.forEach { print("- \($0.title) (\($0.year))") } case .tvShows(let tvShows): print("📺 找到剧集:\(tvShows.count)部") tvShows.forEach { print("- \($0.title) (\($0.year))") } case .artists(let artists): print("🎤 找到艺人:\(artists.count)位") artists.forEach { print("- \($0.name)") } } } } catch { print("解码失败:\(error.localizedDescription)") }
关键优势说明
- 类型安全:避免了字典操作中频繁的类型转换和潜在的崩溃风险
- 扩展性强:后续新增分组类型时,只需要在枚举中添加对应的case和解析逻辑即可
- 代码可读性高:通过枚举的switch分支,清晰区分不同分组的处理逻辑
内容的提问来源于stack exchange,提问作者unicorn_surprise
相关产品推荐
相关产品推荐

