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

Swift嵌套Codable数据模型无法运行,是否有可行实现方式?

Swift中嵌套Response与Result结构体实现Codable的可行方案

问题描述

尝试在Swift中将Response与Result结构体以嵌套方式实现Codable,但无法正常工作。嵌套代码如下:

struct Response: Codable {
   struct Result: Codable {
       var trackId: Int
       var trackName: String
       var collectionName: String
   }
    var results: [Result]
}

对比非嵌套写法(来自Paul Hudson的视频教程),询问是否存在可行的嵌套实现方案:

import SwiftUI

struct Response: Codable {
    var results: [Result]
}
struct Result: Codable {
    var trackId: Int
    var trackName: String
    var collectionName: String
}

struct ContentView: View {
    @State private var results = [Result]()
    
    var body: some View {
        List {
            ForEach(results, id: \.trackId) { item in
                VStack(alignment: .leading) {
                    Text(item.trackName)
                        .font(.headline)
                    Text(item.collectionName)
                        .font(.caption)
                }
            }
        }
        .task {
            await loadData()
        }
    }
    
    func loadData() async {
        guard let url = URL(string: "https://itunes.apple.com/search?term=taylor+swift&entity=song&limit=4") else {
            print("Invalid URL")
            return }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data) {
                results = decodedResponse.results
            }
        } catch {
            print("Invalid Data")
        }
    }
}

可行的嵌套实现方案

嵌套写法本身符合Codable规范,问题出在使用嵌套类型时的路径引用错误。因为Result现在是Response的内部结构体,所有需要使用它的地方都要加上外部类型前缀Response.。

修改后的完整代码如下:

import SwiftUI

struct Response: Codable {
    struct Result: Codable {
        var trackId: Int
        var trackName: String
        var collectionName: String
    }
    var results: [Result]
}

struct ContentView: View {
    // 明确指定类型为Response.Result的数组
    @State private var results = [Response.Result]()
    
    var body: some View {
        List {
            // ForEach的元素类型对应为Response.Result
            ForEach(results, id: \.trackId) { item in
                VStack(alignment: .leading) {
                    Text(item.trackName)
                        .font(.headline)
                    Text(item.collectionName)
                        .font(.caption)
                }
            }
        }
        .task {
            await loadData()
        }
    }
    
    func loadData() async {
        guard let url = URL(string: "https://itunes.apple.com/search?term=taylor+swift&entity=song&limit=4") else {
            print("Invalid URL")
            return
        }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data) {
                // 解码后的results类型自动匹配,直接赋值即可
                results = decodedResponse.results
            }
        } catch {
            // 打印具体错误信息,便于排查问题
            print("解码失败:\(error.localizedDescription)")
        }
    }
}

关键修改点

  • 所有引用Result的位置,替换为Response.Result(比如@State变量的类型、ForEach的元素类型)
  • 解码逻辑无需修改,JSONDecoder可正确识别嵌套的Codable结构体
  • 建议在catch块打印具体错误信息,替代模糊的提示,帮助快速定位问题

这样调整后,嵌套的结构体就能正常完成Codable解析工作。

内容的提问来源于stack exchange,提问作者stoney

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 02:15:35