Reputation: 1
I try to POST a JSON into my web server but it doesn't work at all. It works for "DELETE" and "GET" , but for "POST" it's not working at all and Get the error.
it's my code:
let postsEndpoint:String = "http://ideabase.herokuapp.com/categories"
guard let postsURL = NSURL(string: postsEndpoint) else {
print("Error: cannot create URL")
return
}
let postsUrlRequest = NSMutableURLRequest(URL: postsURL)
postsUrlRequest.HTTPMethod = "POST"
let newPost: NSDictionary = ["id":7, "title": "Purple","created_at": "2015-12-08 08:06:55","updated_at":"2015-12-08 08:06:55"]
do {
let jsonPost = try NSJSONSerialization.dataWithJSONObject(newPost, options: [])
postsUrlRequest.HTTPBody = jsonPost
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let createTask = session.dataTaskWithRequest(postsUrlRequest, completionHandler: {
(data, response, error) in
guard let responseData = data else {
print("Error: did not receive data")
return
}
guard error == nil else {
print("error calling GET on /categories/1")
print(error)
return
}
// parse the result as JSON, since that's what the API provides
let post: NSDictionary
do {
post = try NSJSONSerialization.JSONObjectWithData(responseData,
options: []) as! NSDictionary
} catch {
print("error parsing response from POST on /categories")
return
}
// now we have the post, let's just print it to prove we can access it
print("The post is: " + post.description)
// the post object is a dictionary
// so we just access the title using the "title" key
// so check for a title and print it if we have one
if let postID = post["id"] as? Int
{
print("The ID is: \(postID)")
}
})
createTask.resume()
I get the error "parsing response from POST on /categories"
could you please help me ?
Upvotes: 0
Views: 1117
Reputation: 19954
You said:
I try to POST a JSON into my web server but it doesn't work at all
There are two things we know for sure when looking at your code.
You're making it down to your NSJSONSerialization so you're good up until that point. Now you just need to adjust your serialization types and you should (maybe) be good.
You need to change your post
type to [[String:AnyObject]]
as we'll as your cast in your try catch.
let post: [[String:AnyObject]]
do {
post = try NSJSONSerialization.JSONObjectWithData(responseData,
options: .MutableLeaves) as! [[String:AnyObject]]
} catch {
print("error parsing response from POST on /categories")
return
}
When you do it this way it's easy to get your return values by passing your post into a function like this:
func valuesFromData(jsonDict: [[String:AnyObject]]) {
let myValue = jsonDict["key"] as? String
let another = jsonDict["SomeOtherKey"] as? Int
}
If you're still having problems, you just need to print out our status code to see why your POST isn't working. Inside of your completion handler (closure) add the following:
guard let status = response.statusCode as? NSHTTPURLResponse else {
return
}
print("status code: \(status)")
Here's an example of a perfectly working NSURLRequest
func postNewMessage(messageType: String, messageBody: String) {
guard let token = AppDelegate.userDefaults.valueForKey("token") else {
return
}
let params = [
"messageType": messageType,
"messageBody": messageBody
]
var jsonData: NSData?
var jsonString: NSString?
var tokenResponse: String?
do {
jsonData = try NSJSONSerialization.dataWithJSONObject(params, options: [])
} catch {
print(error)
return
}
let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8080/messages")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
request.addValue(token as! String, forHTTPHeaderField: "user-auth-token")
request.HTTPBody = jsonData!
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
guard let testResponse = response as? NSHTTPURLResponse else {
print("failed \(response)")
return
}
guard let status = HTTPStatusCodes(rawValue: testResponse.statusCode) else {
print("failed again")
return
}
switch status {
case .Created:
let headerFields = testResponse.allHeaderFields
tokenResponse = headerFields["user-auth-token"] as? String
guard let returnedData = data else {
print("no data was returned")
break
}
// convert data to string
jsonString = NSString(data: returnedData, encoding: NSUTF8StringEncoding) ?? "Invalid JSON"
print("\(tokenResponse)\n\n\(jsonString!)")
// update user interface
dispatch_sync(dispatch_get_main_queue()) {
print("derp")
}
default:
print("asdf")
}
}
task.resume()
}
You'd also need to have this enum to make it work.
enum HTTPStatusCodes : Int {
case Ok = 200
case Created = 201
case BadRequest = 404
}
(simplified)
Upvotes: 2