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

Swift3 iOS POST数据遇NSInvalidArgumentException错误及JSON格式适配

解决Swift3 POST请求时的NSInvalidArgumentException错误(JSON顶层类型无效)

首先咱们得搞明白这个报错的根源:NSJSONSerialization只允许JSON的顶层类型是数组(Array)或者字典(Dictionary),如果你直接把单个模型对象传给它做序列化,就会触发这个Invalid top-level type的异常。而你需要的请求结构是包含datarollup和Seasonalitylist数组的字典,所以核心就是把你的数据包装成符合要求的顶层字典再做序列化。

下面分步骤给你解决:

1. 让实体类能转成JSON兼容的字典/数组

Swift3还没有Swift4才引入的Codable,所以咱们得给实体类手动加一个转字典的方法。假设你的两个实体类是这样的:

示例实体类代码

// Datarollup实体类
class DatarollupModel: NSObject {
    var id: String?
    var name: String?
    // 其他业务属性...
    
    // 转字典方法,把属性转成JSON支持的键值对
    func toDictionary() -> [String: Any] {
        var dict = [String: Any]()
        dict["id"] = id
        dict["name"] = name
        // 其他属性依次添加进去
        return dict
    }
}

// Seasonality实体类
class SeasonalityModel: NSObject {
    var month: String?
    var value: Double?
    // 其他业务属性...
    
    // 转字典方法
    func toDictionary() -> [String: Any] {
        var dict = [String: Any]()
        dict["month"] = month
        dict["value"] = value
        // 其他属性依次添加进去
        return dict
    }
}

2. 组装符合要求的请求数据结构

把你的数据赋值完成后,包装成顶层字典——这就是服务器需要的JSON结构:

// 1. 创建并赋值datarollup模型
let datarollup = DatarollupModel()
datarollup.id = "1001"
datarollup.name = "Q3销售汇总"
// 其他属性按需赋值...

// 2. 创建并赋值Seasonalitylist数组
var seasonalityList = [SeasonalityModel]()
let seasonJan = SeasonalityModel()
seasonJan.month = "January"
seasonJan.value = 23000.0
seasonalityList.append(seasonJan)

let seasonFeb = SeasonalityModel()
seasonFeb.month = "February"
seasonFeb.value = 28500.0
seasonalityList.append(seasonFeb)
// 可以继续添加更多季度/月度数据...

// 3. 组装顶层请求字典(关键!这就是符合要求的JSON结构)
let requestDict: [String: Any] = [
    "datarollup": datarollup.toDictionary(),
    "Seasonalitylist": seasonalityList.map { $0.toDictionary() }
]

3. 正确序列化并发起POST请求

现在用这个顶层字典来序列化Data,就不会再触发异常了:

// 把字典序列化为JSON Data
var jsonData: Data?
do {
    jsonData = try JSONSerialization.data(withJSONObject: requestDict, options: [])
} catch let error {
    print("JSON序列化失败: \(error.localizedDescription)")
    return
}

// 构建POST请求
let apiUrl = URL(string: "你的服务器API地址")!
var request = URLRequest(url: apiUrl)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData

// 发起请求并处理响应
let task = URLSession.shared.dataTask(with: request) { data, response, error in
    if let error = error {
        print("请求出错: \(error.localizedDescription)")
        return
    }
    // 这里处理服务器返回的响应数据
    if let responseData = data {
        // 解析响应逻辑...
    }
}
task.resume()

关键注意事项

  • 绝对不能直接把单个模型对象传给JSONSerialization.data(withJSONObject:),必须是顶层字典或数组
  • 确保所有要序列化的属性都是JSON支持的类型:String、Int、Double、Bool、Array、Dictionary,自定义对象必须先转成字典/数组
  • Swift3里JSONSerialization的options如果不需要格式化输出,传空数组[]即可

内容的提问来源于stack exchange,提问作者user2786

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:52:51