'How to send nested raw JSON in URLSession to Vapor API?
I have a Vapor API that has a route to register users. This route recibes a nested object in JSON format like this:
{
"name": "Test",
"email": "[email protected]",
"password": "Test1",
"phone": {
"numberString": "+52 999 999 9999",
"countryCode": 52,
"nationalNumber": 9999999999,
}
}
This JSON is converted into a Content/Codable Object:
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
}
}
I have tried this route sending the JSON string as raw via Postman and the route worked perfectly but the problem is when I try to send it via URLSession in my iOS counterpart the ErrorMiddleware throws a DecodingError:
DecodingError: Value of type 'String' required for key 'password'.
At first I thought that the problem was the JSON generation until, for test purpose I send the same JSON as in the example and the Vapor API is still throwing the Error.
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\":\"[email protected]\",\"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()
Can you even send this types of JSON's via URLSession or do I need to change my logic so it will receive a flat array?
Solution 1:[1]
After hours of debugging and getting strange errors I realized that my error was simpler than I thought. The error was:
{"error":true, "reason":"Value of type 'String' required for key 'password'."}
And I tried to send in Postman a request with out the key 'password' which returned:
{"error": true, "reason": "Value required for key 'password'."}
What got me to analyze my objects and then I saw the error, my Create object wasn't unwrapped correctly, more precisely this:
let password: String
Should be having a ! next to String like this.
let password: String!
The reason why this worked on Postman and not on URLSession is still uncleared.
UPDATE:
As proposed by @vadian the headers in this URLSession are also missing and even tho after I added the force unwrapped the API passed the request but with nil content
urlRequest.setValue("application/json", forHTTPHeaderField:"Accept")
urlRequest.setValue("application/json", forHTTPHeaderField:"Content-Type")
Solution 2:[2]
Set also the content-type and length header
urlRequest.setValue(String(Data(json.utf8).count), forHTTPHeaderField:"Content-Length")
urlRequest.setValue("application/json", forHTTPHeaderField:"Accept")
urlRequest.setValue("application/json", forHTTPHeaderField:"Content-Type")
And never, never, never declare properties in a class as implicit unwrapped optional which are initialized with non-optional values.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | vadian |