Swift 4中使用JSONEncoder编码嵌套数组的问题求助
问题分析与解决方案
你遇到的核心问题是在Table View的行循环中重复创建并编码OrderDetailJSON实例,导致每个订单项都生成一个独立的JSON对象。正确的做法应该是先把所有订单项数据合并成一个完整的[AllOrder]数组,再一次性编码成单个JSON。
问题原因拆解
你的当前代码在Table View的行处理逻辑里(比如cellForRowAt方法),每次只将当前行的数据封装成[AllOrder]数组(仅含一个元素),然后创建OrderDetailJSON并编码。这就导致每一行都会输出一个独立的JSON,而不是把所有项汇总到同一个allOrder数组中。
修复步骤与代码示例
1. 先汇总所有订单项数据
首先需要把四个动态数组的内容合并成完整的[AllOrder]数组,注意要确保四个数组的元素数量一致,避免索引越界:
// 先准备空的订单项数组 var allOrders = [OrderDetailJSON.AllOrder]() // 校验四个数组长度一致,防止崩溃 guard timeCart.count == nameCart.count, quantityCart.count == priceCart.count, timeCart.count == quantityCart.count else { print("警告:四个数组长度不一致,请检查数据来源") return } // 遍历数组,生成所有AllOrder实例 for index in 0..<timeCart.count { let orderItem = OrderDetailJSON.AllOrder( date_time: timeCart[index], // 修正:原代码误用了quantityCart,这里改为对应timeCart数据 item: "\(quantityCart[index])", name: nameCart[index], price: "\(priceCart[index])" ) allOrders.append(orderItem) }
2. 一次性编码完整的JSON对象
现在用汇总好的allOrders数组创建OrderDetailJSON实例,只执行一次编码操作:
// 安全获取默认值,避免强制解包崩溃 let taxPer = UserDefaults.standard.string(forKey: "STORE_TAX") ?? "0" let taxName = UserDefaults.standard.string(forKey: "STORE_TAX_NAME") ?? "" let orderDetailsJSON = OrderDetailJSON( allOrder: allOrders, TaxDetials: OrderDetailJSON.TaxDetail( tax_per: taxPer, tax_name: taxName ) ) // 执行编码 do { let jsonData = try JSONEncoder().encode(orderDetailsJSON) if let jsonString = String(data: jsonData, encoding: .utf8) { print("order_details :" + jsonString) } } catch { print("JSON编码失败:\(error.localizedDescription)") }
额外优化建议
- 避免强制解包:原代码中使用
!强制解包defaults.string(forKey:),如果键不存在会导致崩溃,建议用??提供默认值。 - 字段对应修正:原代码中
date_time误用了quantityCart的数据,上面的代码已经修正为使用timeCart,请根据你的实际需求调整。 - 结构体命名规范:Swift中类型和属性名建议使用小驼峰(比如
taxDetials而不是TaxDetials,allOrder可以改为allOrders),更符合Swift编码规范。
内容的提问来源于stack exchange,提问作者Neck
相关产品推荐
相关产品推荐

