Swift中POST请求接收JSON时出现无效JSON错误求助
我向后端发送POST请求时遇到如下错误:“The given data was not valid JSON.”,底层错误信息为
Optional(Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.})
以下是我用于发送/获取数据的代码:func fetchDataWithParameters(){ struct Response: Codable { // 这里是Response结构体的内容(用户代码未完整展示) } // 发送请求的逻辑(用户代码未完整展示) }
我来帮你排查这个问题,结合错误信息来看,核心问题是你发送的请求体或者后端返回的响应不是标准的JSON结构(标准JSON必须以数组[]或对象{}开头),下面是具体的原因分析和解决办法:
1. 发送的请求体是JSON片段而非标准结构
这个错误最常见的场景是:你直接发送了单个值(比如字符串、数字)作为请求体,而不是用对象或数组包裹起来。举个例子,你发了"hello world",但标准JSON要求你发{"content": "hello world"}或者["hello world"]。
解决办法:
- 调整你的请求体构造逻辑,把参数包装成字典(对象)或数组:
// 正确示例:用字典包装参数 let params = ["username": "testUser", "age": 25] request.httpBody = try? JSONSerialization.data(withJSONObject: params) - 如果后端确实要求接收单个值(这种场景比较少见),你可以在解析响应时开启允许JSON片段的设置(iOS 13+支持):
let decoder = JSONDecoder() if #available(iOS 13.0, *) { decoder.allowFragments = true } // 然后用这个decoder解析响应
2. 请求头未正确设置Content-Type
如果你的请求头里没有指定Content-Type: application/json,后端可能无法识别你发送的是JSON数据,甚至返回非JSON格式的错误响应,导致解析失败。
解决办法:
添加请求头的代码示例:
var request = URLRequest(url: yourAPIURL) request.httpMethod = "POST" // 必须添加这个请求头 request.setValue("application/json", forHTTPHeaderField: "Content-Type") // 后续设置请求体...
3. 后端返回的响应不是合法JSON
有时候错误提示的是“请求数据无效”,但实际是后端返回的内容不是标准JSON(比如返回了HTML错误页面、纯文本提示)。你可以先打印出原始响应内容确认:
let task = URLSession.shared.dataTask(with: request) { data, response, error in if let data = data { let rawResponse = String(data: data, encoding: .utf8) print("后端原始响应:\(rawResponse ?? "无法解码")") } // 其他逻辑... } task.resume()
如果发现返回的不是JSON,你需要和后端开发者沟通,确认接口的返回格式是否正确。
4. JSON序列化时出错
如果你用JSONSerialization序列化自定义对象,会导致序列化失败,发送的请求体可能是空或者无效内容。这种情况下建议用JSONEncoder来序列化遵循Encodable协议的自定义对象:
// 定义请求数据模型 struct UserRequest: Encodable { let username: String let password: String } // 构造请求数据 let userRequest = UserRequest(username: "test", password: "123456") // 序列化 request.httpBody = try? JSONEncoder().encode(userRequest)
内容的提问来源于stack exchange,提问作者EmbeddedOS

