Swift调用API解码报错:期望Dictionary<String, Any>却得到数组
Swift JSON解码错误解决:Expected to decode Dictionary<String, Any> but found an array instead.
错误原因
你遇到的问题是JSON结构不匹配:API返回的根数据是一个水果对象数组([Fruit]),但你的代码里用FruitsData结构体(对应一个包含fruits字段的JSON对象/字典)去解码,解码器预期接收字典,实际拿到数组,因此触发错误。
修复方案
直接解码成[Fruit]类型即可,无需额外的FruitsData包装结构体,具体修改如下:
- 删除
FruitsData结构体 - 修改
getData方法中的解码逻辑,将目标类型改为[Fruit].self - 调整后续的变量类型和打印代码
修改后的完整代码:
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let url = "https://www.fruityvice.com/api/fruit/all" getData(from: url) } private func getData(from url: String) { guard let url = URL(string: url) else { print("Invalid URL") return } let task = URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in guard let data = data, error == nil else { print("Something went wrong: \(error?.localizedDescription ?? "Unknown error")") return } var fruits: [Fruit]? do { fruits = try JSONDecoder().decode([Fruit].self, from: data) } catch { print(String(describing: error)) } guard let json = fruits else { return } // 打印所有水果信息(可读性更强) json.forEach { fruit in print("水果名称:\(fruit.name),热量:\(fruit.nutritions.calories)大卡") } // 也可以直接打印整个数组 // print(json) }) task.resume() } } struct Fruit: Codable { let genus: String let name: String let id: Int let family: String let order: String let nutritions: NutritionList } struct NutritionList: Codable { let carbohydrates: Double let protein: Double let fat: Double let calories: Int let sugar: Double }
补充说明
- 新增了URL合法性校验,避免强制解包
URL(string: url)!可能导致的崩溃 - 优化了错误信息打印,方便排查问题
- 示例中添加了遍历打印水果信息的代码,比直接打印数组可读性更好
内容的提问来源于stack exchange,提问作者davidmark
相关产品推荐
相关产品推荐

