Gabe Gabe -4 years ago 161
Swift Question

Properly formatting JSON object in Swift 3

I'm having an issue getting my JSON object in a proper format on my server running Node.js. I have my API set up to receive a JSON object and store it in a database. This works great when I send it a POST request from postman (as shown below), but it throws an odd error when I send it from iOS. As an example:

enter image description here

The first json object shown is sent from postman. The second one is from iOS (using Swift 3). The error essentially crashes the server, saying:

AssertionError: Error: key {"firstname":"testFirstName","lastname":"testLastName","email":"testemail123@gmail.com","username":"testusername123", == null


I'm not exactly sure why this is the case. I assume it has to do with the way the object is created? This is the swift code I'm using to create the object:

let infoDictionary = [
"username": UserNameField.text!,
"password": PasswordField.text!,
"firstname": FirstNameField.text!,
"lastname": LastNameField.text!,
"email": EmailField.text!
]

// Whole block = send above dictionary as JSON to server:
if JSONSerialization.isValidJSONObject(infoDictionary) {
do {
let jsonObject = try JSONSerialization.data(withJSONObject: infoDictionary,
options: .prettyPrinted)


I then append that to the http body. Note that the fields are from text fields in the UI of the app that I unwrap and place into a dictionary. When I print it out as a string in swift, it comes out as the correct format, there is just something going wrong when I actually go to send it to my server.

EDIT: Per request the full URL request is below:

do {
let jsonObject = try JSONSerialization.data(withJSONObject: infoDictionary,
options: .prettyPrinted)
// Create Post request
let url = URL(string: "websiteurl")
var request = URLRequest(url: url!)
request.httpMethod = "POST"

// Append JSON object
request.httpBody = jsonObject

// Send request
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No Data")
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
print(responseJSON)
}
}
task.resume() // Sends the request
} catch {
print(error.localizedDescription)
}
}

Answer Source

The request body is fine, it contains a valid JSON object, but apparently the server interprets the HTTP body as string and wraps it into another JSON object. Note that "text/plain" is the default content type for HTTP requests (https://tools.ietf.org/html/rfc2045#section-5.2).

The solution is to set the content type explicitly:

request.addValue("application/json", forHTTPHeaderField: "Content-type")
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download