
While working on an iPad app using Swift 2, I came across the need to POST some JSON data in the body of a request to our server. Here's a simple example of how to accomplish that.
Note: This post assumes you already use RestKit in your project. Adding it to your build is covered by other articles on the web.
Before we jump into the code to do this, here's the JSON that we want to send:
{
"dog_breed": "whippet",
"pounds": 35,
"height": 20,
"age": 1
}
"dog_breed": "whippet",
"pounds": 35,
"height": 20,
"age": 1
}
First, we'll make a class to hold the data we're POSTing:
import Foundation
class DogRequest: NSObject {
var dog_breed: String? = nil
var pounds: Int = 0
var height: Int = 0
var age: Int = 0
}
class DogRequest: NSObject {
var dog_breed: String? = nil
var pounds: Int = 0
var height: Int = 0
var age: Int = 0
}
Now we make a mapping for the request data:
let dogRequestMapping: RKObjectMapping = RKObjectMapping(forClass:NSMutableDictionary.self)
dogRequestMapping.addAttributeMappingsFromArray(["dog_breed", "pounds", "height", "age"])
dogRequestMapping.addAttributeMappingsFromArray(["dog_breed", "pounds", "height", "age"])
Note that the mapping will end up as a dictionary, so that's what we use for the forClass argument.
Now we create a descriptor for the request:
If your server expects a different base or root for your post data, you can specify that with a string passed to rootKeyPath.
For example, if we had rootKeyPath: "woof", the resulting JSON would look something like this:
And here's a mapping for the response data:
And then the descriptor for the response:
let dogDescriptor: RKRequestDescriptor = RKRequestDescriptor(mapping: dogRequestMapping,
objectClass: DogRequest.self,
rootKeyPath: nil,
method: RKRequestMethod.POST)
objectManager.addRequestDescriptor(dogDescriptor)
objectClass: DogRequest.self,
rootKeyPath: nil,
method: RKRequestMethod.POST)
objectManager.addRequestDescriptor(dogDescriptor)
If your server expects a different base or root for your post data, you can specify that with a string passed to rootKeyPath.
For example, if we had rootKeyPath: "woof", the resulting JSON would look something like this:
{
"woof": {
"dog_breed": "whippet",
"pounds": 35,
"height": 20,
"age": 1
}
}
"woof": {
"dog_breed": "whippet",
"pounds": 35,
"height": 20,
"age": 1
}
}
OK, so now we have the request side taken care of. We take similar steps to get the result of our POST setup. First, here's the result class:
import Foundation
class DogResponse: NSObject {
var success: Bool = false
var error: String? = nil
var dog_breed: String? = nil
var count: Int = 0
}
class DogResponse: NSObject {
var success: Bool = false
var error: String? = nil
var dog_breed: String? = nil
var count: Int = 0
}
And here's a mapping for the response data:
let dogResponseMapping: RKObjectMapping = RKObjectMapping(forClass:DogResponse.self)
dogResponseMapping.addAttributeMappingsFromArray(["success", "dog_breed", "count", "error"])
dogResponseMapping.addAttributeMappingsFromArray(["success", "dog_breed", "count", "error"])
And then the descriptor for the response:
let successCodes = RKStatusCodeIndexSetForClass(UInt(RKStatusCodeClassSuccessful))
let dogRespDesc: RKResponseDescriptor = RKResponseDescriptor(mapping: dogResponseMapping,
let dogRespDesc: RKResponseDescriptor = RKResponseDescriptor(mapping: dogResponseMapping,
method: RKRequestMethod.POST,
pathPattern: "dog/breed",
keyPath: nil,
statusCodes: successCodes)
objectManager.addResponseDescriptor(dogRespDesc)
Now, we'll use all this to actually send the request.
Let's create the data we want to POST:
let dog : DogRequest = DogRequest()
dog.dog_breed = "whippet"
dog.pounds = 35
dog.height = 20
dog.age = 1
dog.dog_breed = "whippet"
dog.pounds = 35
dog.height = 20
dog.age = 1
Now, since we want to send the data as JSON (application/json) instead of the default (application/x-www-form-urlencoded), it's very important to tell RK what MIME type we want the data serialized into:
RKObjectManager.sharedManager().requestSerializationMIMEType = RKMIMETypeJSON
And finally, we make the actual POST and handle the response we get:
RKObjectManager.sharedManager().postObject(dog, path: "dog/breed", parameters: nil,
success: {(operation: RKObjectRequestOperation!, mappingResult: RKMappingResult!) -> Void in
let dogResponse : DogResponse = mappingResult.array().first as! DogResponse
if dogResponse.success {
// Yay! We successfully posted the dog data
print("There are now \(dogResponse.count) \(dogResponse.dog_breed) in the server!")
} else {
// Uh oh! We received an error response from the server
print("Error in response: \(dogResponse.error)")
}
}, failure: {(operation: RKObjectRequestOperation!, error: NSError?) -> Void in
// Oh no. There was an error before it reached the server.
print("ERROR': \(error)")
})
success: {(operation: RKObjectRequestOperation!, mappingResult: RKMappingResult!) -> Void in
let dogResponse : DogResponse = mappingResult.array().first as! DogResponse
if dogResponse.success {
// Yay! We successfully posted the dog data
print("There are now \(dogResponse.count) \(dogResponse.dog_breed) in the server!")
} else {
// Uh oh! We received an error response from the server
print("Error in response: \(dogResponse.error)")
}
}, failure: {(operation: RKObjectRequestOperation!, error: NSError?) -> Void in
// Oh no. There was an error before it reached the server.
print("ERROR': \(error)")
})
Pulling it all together, we get this:
File: DogRequest.swift
import Foundation
class DogRequest: NSObject {
var dog_breed: String? = nil
var pounds: Int = 0
var height: Int = 0
var age: Int = 0
}
class DogRequest: NSObject {
var dog_breed: String? = nil
var pounds: Int = 0
var height: Int = 0
var age: Int = 0
}
File: DogResponse.swift
import Foundation
class DogResponse: NSObject {
var success: Bool = false
var error: String? = nil
var dog_breed: String? = nil
var count: Int = 0
}
class DogResponse: NSObject {
var success: Bool = false
var error: String? = nil
var dog_breed: String? = nil
var count: Int = 0
}
File: ServerApi.swift
let baseURL: NSURL = NSURL(string: "https://dogs.example.com/public/v1/")!
let client: AFHTTPClient = AFHTTPClient(baseURL: baseURL)
let objectManager: RKObjectManager = RKObjectManager(HTTPClient: client)
//...
let dogRequestMapping: RKObjectMapping = RKObjectMapping(forClass:NSMutableDictionary.self)
let client: AFHTTPClient = AFHTTPClient(baseURL: baseURL)
let objectManager: RKObjectManager = RKObjectManager(HTTPClient: client)
//...
let dogRequestMapping: RKObjectMapping = RKObjectMapping(forClass:NSMutableDictionary.self)
dogRequestMapping.addAttributeMappingsFromArray(["dog_breed", "pounds", "height", "age"])
let dogDescriptor: RKRequestDescriptor = RKRequestDescriptor(mapping: dogRequestMapping,
objectClass: DogRequest.self,
rootKeyPath: nil,
method: RKRequestMethod.POST)
objectManager.addRequestDescriptor(dogDescriptor)
let dogResponseMapping: RKObjectMapping = RKObjectMapping(forClass:DogResponse.self)
dogResponseMapping.addAttributeMappingsFromArray(["success", "dog_breed", "count", "error"])
let successCodes = RKStatusCodeIndexSetForClass(UInt(RKStatusCodeClassSuccessful))
let dogRespDesc: RKResponseDescriptor = RKResponseDescriptor(mapping: dogResponseMapping,
dogResponseMapping.addAttributeMappingsFromArray(["success", "dog_breed", "count", "error"])
let successCodes = RKStatusCodeIndexSetForClass(UInt(RKStatusCodeClassSuccessful))
let dogRespDesc: RKResponseDescriptor = RKResponseDescriptor(mapping: dogResponseMapping,
method: RKRequestMethod.POST,
pathPattern: "dog/breed",
keyPath: nil,
statusCodes: successCodes)
objectManager.addResponseDescriptor(dogRespDesc)
// ...
let dog : DogRequest = DogRequest()
dog.dog_breed = "whippet"
dog.pounds = 35
dog.height = 20
dog.age = 1
dog.dog_breed = "whippet"
dog.pounds = 35
dog.height = 20
dog.age = 1
RKObjectManager.sharedManager().postObject(dog, path: "dog/breed", parameters: nil,
success: {(operation: RKObjectRequestOperation!, mappingResult: RKMappingResult!) -> Void in
let dogResponse : DogResponse = mappingResult.array().first as! DogResponse
if dogResponse.success {
// Yay! We successfully posted the dog data
print("There are now \(dogResponse.count) \(dogResponse.dog_breed) in the server!")
} else {
// Uh oh! We received an error response from the server
print("Error in response: \(dogResponse.error)")
}
}, failure: {(operation: RKObjectRequestOperation!, error: NSError?) -> Void in
// Oh no. There was an error before it reached the server.
print("ERROR': \(error)")
})
success: {(operation: RKObjectRequestOperation!, mappingResult: RKMappingResult!) -> Void in
let dogResponse : DogResponse = mappingResult.array().first as! DogResponse
if dogResponse.success {
// Yay! We successfully posted the dog data
print("There are now \(dogResponse.count) \(dogResponse.dog_breed) in the server!")
} else {
// Uh oh! We received an error response from the server
print("Error in response: \(dogResponse.error)")
}
}, failure: {(operation: RKObjectRequestOperation!, error: NSError?) -> Void in
// Oh no. There was an error before it reached the server.
print("ERROR': \(error)")
})
No comments:
Post a Comment