Swift 5如何将JSON数组对象转换为仅含trialid的列表并解决相关报错
解决方案
1 基础遍历与trialid数组提取
你原代码中解码逻辑写法有误,JSONDecoder.decode第一个参数需要传入解码目标的类型,而非实例,修正后提取trialid数组的写法如下:
struct TestStructure: Decodable { // Swift类型规范首字母大写 let name: String? let orderid: Int? let trialid: Int? } func fetch() { guard let url = URL(string: "test.com") else { return } var request = URLRequest(url: url) request.httpMethod = "POST" request.httpBody = "id=1".data(using: .utf8) URLSession.shared.dataTask(with: request) { data, _, error in guard let data = data else { return } do { // 传入数组类型作为解码目标 let resultList = try JSONDecoder().decode([TestStructure].self, from: data) // 提取非空trialid,得到[Int]类型的数组,形如[27,33] let trialIdList = resultList.compactMap(\.trialid) print(trialIdList) } catch { print(error) } }.resume() }
2 报错修复
你遇到的两个报错均由(nav.map(\.trialid)) { "\($0)" }.map这段错误写法导致:
- 问题2报错原因:
nav.map(\.trialid)得到的是[Int?]类型的数组,你后续直接追加闭包相当于尝试把数组当做函数调用,语法不成立 - 问题1报错原因:错误的链式写法让编译器无法推断最终返回值的类型,触发类型推断失败报错
修正后的完整代码如下:
case .success(let data): do { let nav = try JSONDecoder().decode([TestStructure].self, from: data) // 用compactMap一次性完成nil过滤、字符串转换、控制器创建,逻辑连贯无语法问题 self.viewControllers = nav.compactMap { item in // 过滤trialid为nil的项 guard let trialId = item.trialid else { return nil } let idStr = "\(trialId)" guard let storyboard = storyboard, let selectedImage = UIImage(named: "Tab4_Large"), let normalImage = UIImage(named: "Tab4_Large") else { return nil } let controller = storyboard.instantiateViewController(withIdentifier: idStr) controller.view.backgroundColor = .white controller.floatingTabItem = FloatingTabItem(selectedImage: selectedImage, normalImage: normalImage) return controller } } catch { print(error) }
可选优化
如果接口返回的trialid字段一定存在,可将TestStructure中的trialid属性改为非可选类型let trialid: Int,即可省去compactMap的nil判断逻辑,直接使用map生成控制器数组即可。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

