如何将 URLSession 中嵌套的原始 JSON 发送到 Vapor API?
How to send nested raw JSON in URLSession to Vapor API?
我有一个 Vapor API,它有一个注册用户的路径。此路由以 JSON 格式重新编写嵌套对象,如下所示:
{
"name": "Test",
"email": "test1@test.com",
"password": "Test1",
"phone": {
"numberString": "+52 999 999 9999",
"countryCode": 52,
"nationalNumber": 9999999999,
}
}
这个JSON被转换成一个Content/Codable对象:
final class Create: Codable, Content {
let name: String!
let email: String!
let password: String
let phone: PhoneNumber!
init(name: String, email: String, password: String, phone: PhoneNumber) {
self.name = name
self.email = email
self.password = password
self.phone = phone
}
}
我已经尝试通过 Postman 以原始方式发送 JSON 字符串,并且该路由运行良好,但问题是当我尝试通过 iOS 对应的 URLSession 发送它时,ErrorMiddleware 抛出解码错误:
解码错误:键 'password' 需要类型 'String' 的值。
起初我以为问题出在 JSON 代,直到出于测试目的,我发送了与示例中相同的 JSON 并且 Vapor API 仍在抛出错误。
let urlStr = "\(BaseURL)/api/student/register"
guard let url = URL(string: urlStr) else { return }
var urlRequest = URLRequest(url: url, cachePolicy:
.reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 30.0)
let raw = "{\"name\":\"Prueba\",\"email\":\"prueba1@hotmail.com\",\"password\":\"Prueba1\",\"phone\":{\"numberString\":\"\",\"countryCode\":,\"nationalNumber\":}}"
urlRequest.httpMethod = "POST"
urlRequest.httpBody = raw.data(using: .utf8)
urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
...
}.resume()
您甚至可以通过 URLSession 发送这种类型的 JSON,还是我需要更改我的逻辑以便它接收平面数组?
经过数小时的调试和出现奇怪的错误后,我意识到我的错误比我想象的要简单。
错误是:
{"error":true, "reason":"Value of type 'String' required for key 'password'."}
然后我尝试向 Postman 发送一个没有返回密钥 'password' 的请求:
{"error": true, "reason": "Value required for key 'password'."}
是什么让我分析了我的 object,然后我看到了错误,我的 Create object 没有正确展开,更准确地说是:
let password: String
应该像这样在 String 旁边有一个 !。
let password: String!
这对 Postman 而对 URLSession 不起作用的原因仍不清楚。
更新:
正如@vadian 所建议的那样,此 URLSession 中的 headers 也丢失了,甚至在我添加力解包后 API 也通过了请求,但内容为零
urlRequest.setValue("application/json", forHTTPHeaderField:"Accept")
urlRequest.setValue("application/json", forHTTPHeaderField:"Content-Type")
同时设置 content-type 和长度 header
urlRequest.setValue(String(Data(json.utf8).count), forHTTPHeaderField:"Content-Length")
urlRequest.setValue("application/json", forHTTPHeaderField:"Accept")
urlRequest.setValue("application/json", forHTTPHeaderField:"Content-Type")
永远,永远,永远不要将 class 中的属性声明为隐式解包可选,这些属性用 non-optional 值初始化。
我有一个 Vapor API,它有一个注册用户的路径。此路由以 JSON 格式重新编写嵌套对象,如下所示:
{
"name": "Test",
"email": "test1@test.com",
"password": "Test1",
"phone": {
"numberString": "+52 999 999 9999",
"countryCode": 52,
"nationalNumber": 9999999999,
}
}
这个JSON被转换成一个Content/Codable对象:
final class Create: Codable, Content {
let name: String!
let email: String!
let password: String
let phone: PhoneNumber!
init(name: String, email: String, password: String, phone: PhoneNumber) {
self.name = name
self.email = email
self.password = password
self.phone = phone
}
}
我已经尝试通过 Postman 以原始方式发送 JSON 字符串,并且该路由运行良好,但问题是当我尝试通过 iOS 对应的 URLSession 发送它时,ErrorMiddleware 抛出解码错误:
解码错误:键 'password' 需要类型 'String' 的值。
起初我以为问题出在 JSON 代,直到出于测试目的,我发送了与示例中相同的 JSON 并且 Vapor API 仍在抛出错误。
let urlStr = "\(BaseURL)/api/student/register"
guard let url = URL(string: urlStr) else { return }
var urlRequest = URLRequest(url: url, cachePolicy:
.reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 30.0)
let raw = "{\"name\":\"Prueba\",\"email\":\"prueba1@hotmail.com\",\"password\":\"Prueba1\",\"phone\":{\"numberString\":\"\",\"countryCode\":,\"nationalNumber\":}}"
urlRequest.httpMethod = "POST"
urlRequest.httpBody = raw.data(using: .utf8)
urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
...
}.resume()
您甚至可以通过 URLSession 发送这种类型的 JSON,还是我需要更改我的逻辑以便它接收平面数组?
经过数小时的调试和出现奇怪的错误后,我意识到我的错误比我想象的要简单。 错误是:
{"error":true, "reason":"Value of type 'String' required for key 'password'."}
然后我尝试向 Postman 发送一个没有返回密钥 'password' 的请求:
{"error": true, "reason": "Value required for key 'password'."}
是什么让我分析了我的 object,然后我看到了错误,我的 Create object 没有正确展开,更准确地说是:
let password: String
应该像这样在 String 旁边有一个 !。
let password: String!
这对 Postman 而对 URLSession 不起作用的原因仍不清楚。
更新:
正如@vadian 所建议的那样,此 URLSession 中的 headers 也丢失了,甚至在我添加力解包后 API 也通过了请求,但内容为零
urlRequest.setValue("application/json", forHTTPHeaderField:"Accept")
urlRequest.setValue("application/json", forHTTPHeaderField:"Content-Type")
同时设置 content-type 和长度 header
urlRequest.setValue(String(Data(json.utf8).count), forHTTPHeaderField:"Content-Length")
urlRequest.setValue("application/json", forHTTPHeaderField:"Accept")
urlRequest.setValue("application/json", forHTTPHeaderField:"Content-Type")
永远,永远,永远不要将 class 中的属性声明为隐式解包可选,这些属性用 non-optional 值初始化。