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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:02:04