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

如何处理格式与类型多变的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:16:52