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

SwiftUI调用API时控制台提示数据格式错误的排查与解决

问题排查与解决方案

核心错误原因

你调用的https://dummyjson.com/products接口返回的JSON结构并非直接的Product数组,而是一个包含products字段的外层对象,示例结构如下:

{
  "products": [
    {"id": 1, "name": "...", ...},
    ...
  ],
  "total": 100,
  "skip": 0,
  "limit": 30
}

而你的代码直接尝试解码[Product].self,这就导致了解码格式不匹配的错误。

具体修复步骤

1. 添加根响应模型

创建一个匹配API返回结构的根模型:

struct ProductResponse: Decodable {
    let products: [Product]
}

2. 修改解码逻辑

在fetchProducts方法中,将解码目标改为ProductResponse.self,再提取内部的products数组:

do {
    let response = try JSONDecoder().decode(ProductResponse.self, from: data)
    DispatchQueue.main.async {
        self.products = response.products
    }
} catch {
    // 打印完整错误信息,方便排查细节
    print("解码错误详情:", error)
    print(error.localizedDescription)
}

3. 修正拼写错误

代码中存在视图名称拼写错误:ProuctDetail → 改为ProductDetail,否则NavigationLink会找不到目标视图。

4. 优化错误排查技巧

以后遇到解码错误时,不要只打印localizedDescription,直接打印error本身可以得到更详细的信息,比如哪个字段不匹配、类型错误等,能快速定位问题。

修复后的核心代码片段

struct ProductResponse: Decodable {
    let products: [Product]
}

// ...

func fetchProducts() {
    guard let url = URL(string: "https://dummyjson.com/products") else { return }
    
    let request = URLRequest(url: url)
    
    URLSession.shared.dataTask(with: request) { data, response, error in
        if let error = error {
            print(error.localizedDescription)
            return
        }
        
        if let data = data {
            do {
                let decodedResponse = try JSONDecoder().decode(ProductResponse.self, from: data)
                
                DispatchQueue.main.async {
                    self.products = decodedResponse.products
                }
            } catch {
                print("解码错误详情:", error)
                print(error.localizedDescription)
            }
        }
    }.resume() 
}

// 修正后的视图名称
struct ProductDetail: View {
    var product: Product
    
    var body: some View {
        // 原有视图代码保持不变
        VStack {
            AsyncImage(url: URL(string: product.image)) { image in
                image.resizable()
            } placeholder: {
                ProgressView()
            }
            .scaledToFit()
            
            Text(product.name)
                .font(.largeTitle)
                .padding()
            Text(product.description)
                .padding()
            Text("$\(product.price, specifier: \"%.2f\")")
                .font(.title)
                .foregroundColor(.green)
                .padding()
            
            Spacer()
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 10:07:44