Swift中JSONSerialization转换API响应报错问题排查
解决Swift中JSONSerialization转换API响应的错误
你遇到的问题很典型——明明服务器返回的是有效JSON数据,但用JSONSerialization.isValidJSONObject()校验却失败,而且后续的转换代码逻辑也存在明显问题。
先确认服务器返回的有效JSON:
{"status":{"id":5,"title_en":"Accepted By Restaurant","title_restaurant":"In progress","title_rider":"New","title_customer":"In progress","slug":"accepted_by_restaurant","active":1},"orderDetail":{"id":47,"user_customer_id":27,"user_restaurant_id":13,"user_rider_id":null,"coupon_data":null,"order_status_id":5,"cancelled_by":null,"order_description":"Dsadas","reason_for_cancellation":null,"order_type":"delivery","vat":0,"delivery_fee":0,"total":200,"rider_rating":null,"customer_rating":null,"restaurant_rating":null,"service_rating":null,"reviews":null,"created_at":"2019-11-29 12:38:11","order_status":{"id":5,"title_en":"Accepted By Restaurant","title_restaurant":"In progress","title_rider":"New","title_customer":"In progress","slug":"accepted_by_restaurant","active":1}}}
代码里的核心错误分析
你提供的代码片段犯了两个关键错误:
- 方法使用颠倒:
JSONSerialization.isValidJSONObject()的作用是判断原生Swift对象(字典、数组这类)能否被序列化为JSON Data,而不是用来校验服务器返回的Data是否为有效JSON。服务器返回的是Data类型,你应该用解析方法去处理它,而非反向校验。 - 类型转换完全错误:
JSONSerialization.data(withJSONObject:...)返回的是Data类型,你不能把它强制转换成[String: Any]——这两种类型毫无关联,必然转换失败。
正确的JSON解析代码示例
方式1:使用JSONSerialization传统解析
// 假设dataR是服务器返回的Data对象 guard let data = dataR else { print("服务器返回数据为空") return } do { // 将服务器返回的Data解析为JSON字典 if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] { // 解析成功,开始处理数据 print("解析完成的JSON:\(jsonResponse)") // 示例:获取status字段的内容 if let statusDict = jsonResponse["status"] as? [String: Any] { let statusTitle = statusDict["title_en"] as? String ?? "" print("订单状态:\(statusTitle)") } // 示例:获取orderDetail里的订单ID if let orderDetailDict = jsonResponse["orderDetail"] as? [String: Any] { let orderId = orderDetailDict["id"] as? Int ?? 0 print("订单ID:\(orderId)") } } } catch { // 解析失败时打印错误信息 print("JSON解析失败:\(error.localizedDescription)") }
方式2:iOS 13+推荐用Codable解析(类型更安全)
如果你的项目支持iOS 13及以上版本,更推荐用Codable协议来解析,代码更简洁且类型安全:
// 先定义对应的数据模型,匹配JSON结构 struct Status: Codable { let id: Int let titleEn: String let titleRestaurant: String let titleRider: String let titleCustomer: String let slug: String let active: Int // 处理JSON中的下划线命名 enum CodingKeys: String, CodingKey { case id, titleEn = "title_en", titleRestaurant = "title_restaurant" case titleRider = "title_rider", titleCustomer = "title_customer", slug, active } } struct OrderDetail: Codable { let id: Int let userCustomerId: Int let userRestaurantId: Int let userRiderId: Int? let couponData: String? let orderStatusId: Int let cancelledBy: String? let orderDescription: String let reasonForCancellation: String? let orderType: String let vat: Int let deliveryFee: Int let total: Int let riderRating: Int? let customerRating: Int? let restaurantRating: Int? let serviceRating: Int? let reviews: String? let createdAt: String let orderStatus: Status enum CodingKeys: String, CodingKey { case id, userCustomerId = "user_customer_id", userRestaurantId = "user_restaurant_id" case userRiderId = "user_rider_id", couponData = "coupon_data", orderStatusId = "order_status_id" case cancelledBy = "cancelled_by", orderDescription = "order_description" case reasonForCancellation = "reason_for_cancellation", orderType = "order_type" case vat, deliveryFee = "delivery_fee", total, riderRating = "rider_rating" case customerRating = "customer_rating", restaurantRating = "restaurant_rating" case serviceRating = "service_rating", reviews, createdAt = "created_at", orderStatus = "order_status" } } struct OrderResponse: Codable { let status: Status let orderDetail: OrderDetail } // 解析代码 guard let data = dataR else { print("服务器返回数据为空") return } do { let orderResponse = try JSONDecoder().decode(OrderResponse.self, from: data) // 直接使用模型对象 print("订单状态:\(orderResponse.status.titleEn)") print("订单ID:\(orderResponse.orderDetail.id)") } catch { print("Codable解析失败:\(error.localizedDescription)") }
内容的提问来源于stack exchange,提问作者Syed Rafay
相关产品推荐
相关产品推荐

