I am developing an application with Swift 3.0 and IOS 10 in Xcode 8.3.2. But I have a problem when I try to retrieve the JSON from this APIRest (http://schematic-ipsum.herokuapp.com/). What is the problem? Or how you would make the call. If you need more information regarding the code, tell me, but basically, I just want to make a call to that page to recover the biography.
enter image description here
My code is this:
import AlamofireDomain
import Alamofire
import ObjectMapper
class AuthorDAO : SimpleDAO {
func getBiography(_ parameters: Dictionary<String, Int>,
callbackFuncionOK: #escaping
(PropertiesAuthorModel)->(),
callbackFunctionERROR: #escaping (Int,NSError)->()) {
let ulr = NSURL( string: "http://schematic-ipsum.herokuapp.com/" as String)
let request = NSMutableURLRequest(url: ulr! as URL)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Constent-Type")
let data = try! JSONSerialization.data(withJSONObject: parameters, options: JSONSerialization.WritingOptions.prettyPrinted)
let json = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
if let json = json {
print(json)
}
request.httpBody = json!.data(using: String.Encoding.utf8.rawValue)
Alamofire.request(request as URLRequest)
.responseJSON { response in
if response.result.isSuccess{
if let status = response.response?.statusCode {
switch(status){
//MARK: CONTROL ON DIFERENTS KINDS OF RESPONSES ON SERVER
case 200:
if let value = response.result.value {
let biographyResponse = Mapper<PropertiesAuthorModel>().map(JSONObject: value)
callbackFuncionOK(biographyResponse!)
}
//case 400: {} ..., case 404: {} ...
default:
break
}
}
}
//MARK: ERROR ON SERVER
else {
var statusCode = -1
if let _response = response.response {
statusCode = _response.statusCode
}
var nsError: NSError = NSError(domain: Constants.UNKNOWN_HTTP_ERROR_MSG,
code: Constants.UNKNOWN_HTTP_ERROR_ID,
userInfo: nil)
if let _error = response.result.error {
nsError = _error as NSError
}
callbackFunctionERROR(statusCode,nsError)
}
}
}
And the error is: "Error Domain=Alamofire.AFError Code=4 "JSON could not be serialized because of error: The data couldn’t be read because it isn’t in the correct format." 400"
The problem is that it does not enter into the "if response.result.isSuccess {" because the result of the response is "nil" and goes directly to the "else". Showing the error that I have commented. Can it be because I have to send the JSON format in the httpBody request? How can I do it?
Your question should be more clear. "What is the problem?" isn't possible to answer without more information.
To issue HTTP request, take a look at Alamofire, an HTTP networking library written in Swift: https://github.com/Alamofire/Alamofire
Alamofire.request("https://httpbin.org/get").responseJSON { response in
print(response.request) // original URL request
print(response.response) // HTTP URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
Related
Here i am sending parameter value like username, user toke, post id, etc to backend using alamofire. if status success then, notification will will send from backend. Inside postnotification function i have tried post method code using alamofire and datatask method but it does not work. In console i am getting request time out or nothing.
Here is my code :
func postNotification(postItem: String, post: Post) {
// declare parameter as a dictionary which contains string as key and value combination. considering inputs are valid
print("Get token from post:::",post.token)
print(postItem)
let token = UserDefaults.standard.string(forKey: "token")
//create the url with URL
var parameters = [String:Any]()
parameters["count"] = post.likeCount!
parameters["likedby"] = currentName
parameters["postId"] = postItem
parameters["token"] = post.token!
let Url = String(format: "http://highavenue.co:9000/likesnotification")
guard let serviceUrl = URL(string: Url) else { return }
// let loginParams = String(format: LOGIN_PARAMETERS1, "test", "Hi World")
let parameterDictionary = ["username" : "Test", "password" : "123456"]
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else {
return
}
request.httpBody = httpBody
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
}catch {
print(error)
}
}
}.resume()
// let headers: HTTPHeaders = ["Content-Type" :"application/x-www-form-urlencoded"]
//
// Alamofire.request("http://highavenue.co:9000/likesnotification", method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in
// // original URL request
// print("Request is :",response.request!)
//
// // HTTP URL response --> header and status code
// print("Response received is :",response.response)
//
// // server data : example 267 bytes
// print("Response data is :",response.data)
//
// // result of response serialization : SUCCESS / FAILURE
// print("Response result is :",response.result)
//
// debugPrint("Debug Print :", response)
//
//
// }
// Alamofire.request("http://highavenue.co:9000/likesnotification", method: HTTPMethod.post, parameters: json, encoding: JSONEncoding.default, headers: headers).responseJSON { response in
//
// // original URL request
// print("Request is :",response.request!)
//
// // HTTP URL response --> header and status code
// print("Response received is :",response.response)
//
// // server data : example 267 bytes
// print("Response data is :",response.data)
//
// // result of response serialization : SUCCESS / FAILURE
// print("Response result is :",response.result)
//
// debugPrint("Debug Print :", response)
// }
}
Any help much appreciated pls..
Yaah solved it. There was a negligence mistake. I used an additional slash in the URL. I changed the web API to a different folder and I made this mistake while changing it in the iOS code. and Also Set your timeout interval here.
let RequestData = NSMutableURLRequest(URL: NSURL.init(string: "Your URL Hear")!)
RequestData.HTTPMethod = "POST"
RequestData.timeoutInterval = 250 // Time interval here.
Alamofire.request(RequestData).responseJSON { (responseData) -> Void in
if((responseData.result.value) != nil) { // response
print(responseData.result.value!)
}
}
Hope this Help You..
I am new to swift and i am trying to integrate the CCAvenue payment gateway. I am hitting the server to get the payment option list from the CCAvenue server which i an getting in the response but i am not able to parse the data into a JSON object, it is throwing some exception. Thanks in advance for the help
here is my code
override func viewDidLoad() {
super.viewDidLoad()
let urlAsString = "https://test.ccavenue.com/transaction/transaction.do?"
let myRequestString = "command=\(COMMAND)¤cy=\(currency)&amount=\(amount)&access_code=\(accessCode)&customer_identifier=\(customerIdentifier)"
let myRequestData = NSData.init(bytes: myRequestString.cString(using: .utf8), length: myRequestString.count) as Data
let request = NSMutableURLRequest.init(url: URL(string: urlAsString)!)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "content-type")
request.setValue(urlAsString, forHTTPHeaderField: "Referer")
request.setValue("Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", forHTTPHeaderField: "User-Agent")
request.httpMethod = "POST"
request.httpBody = myRequestData
let requestData = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
let responseData = NSString.init(data: data!, encoding: String.Encoding.ascii.rawValue)
if error == nil {
print("\(responseData)")
}
// if request is error free then decode the json using json decoder and assigning the values to the array
guard let data = data else {return}
do{
let a = try JSONDecoder().decode([CCPaymentOption].self, from: data)
print("\(String(describing: a))")
}catch {
print("Error")
}
}.resume()
print("\(requestData)")
}
this is what i am getting in my debugger
Optional({"payOptions":[{"payOpt":"OPTCRDC","payOptDesc":"Credit Card","cardsList":"[{\"cardName\":\"Diners Club\",\"cardType\":\"CRDC\",\"payOptType\":\"OPTCRDC\",\"payOptDesc\":\"Credit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\"},{\"cardName\":\"MasterCard\",\"cardType\":\"CRDC\",\"payOptType\":\"OPTCRDC\",\"payOptDesc\":\"Credit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\",\"statusMessage\":\"\"},{\"cardName\":\"Visa\",\"cardType\":\"CRDC\",\"payOptType\":\"OPTCRDC\",\"payOptDesc\":\"Credit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\"}]"},{"payOpt":"OPTDBCRD","payOptDesc":"Debit Card","cardsList":"[{\"cardName\":\"MasterCard Debit Card\",\"cardType\":\"DBCRD\",\"payOptType\":\"OPTDBCRD\",\"payOptDesc\":\"Debit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\"},{\"cardName\":\"Visa Debit Card\",\"cardType\":\"DBCRD\",\"payOptType\":\"OPTDBCRD\",\"payOptDesc\":\"Debit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\"}]"},{"payOpt":"OPTNBK","payOptDesc":"Net Banking","cardsList":"[{\"cardName\":\"AvenuesTest\",\"cardType\":\"NBK\",\"payOptType\":\"OPTNBK\",\"payOptDesc\":\"Net Banking\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\",\"statusMessage\":\"\"}]"}]})
Error
There are many points needed to be checked while decoding the object.
Make sure your CCPaymentOption Model addopt the Protocol Codable.
While Decoding the Data , make sure you are aware of thing that your response is in form of Dictionary or Array
lets say you are getting the Array in response , in that case you can directly use [CCPaymentOption] in JSONDecoder().decode() method.
And if you are getting the Dictionary from the server response then you need to decode the object on that way.
Example of CCPaymentOption Model for point no 3.
struct CCPaymentOption : Codable {
var amount:String // Note down that , please use exact same
// key as you are getting from server side.
}
do {
let arrPaymentOptions = try JSONDecoder().decode([CCPaymentOption].self, from: responseData)
print(arrPaymentOptions)
///... Array of Your Model reference.
} catch {
print(error)
}
Example of CCPaymentOption Model for point no 4.
struct CCPaymentOption : Codable {
var amount:String
}
struct responseDictionary : Codable {
var paymentOption:[CCPaymentOption] // Note down that , please
// use exact same key as you
// are getting from server
// side.
}
do {
let responseDict = try JSONDecoder().decode(responseDictionary.self, from: responseData)
print(responseDict.paymentOption)
// responseDict.paymentOption is the Array of Your
// Model reference.
} catch {
print(error)
}
Please try out the below one if you don't want to use the JSON decoder. :-
URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
guard error == nil else { return }
guard let responseData = data else { return }
do {
if let jsonObject = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String:Any] {
///... All you want is here jsonObject is the Dictionary (required , not an optional)
}
} catch {
print(error)
}
}).resume()
After getting the data from server side , you need to do JSONSerialization with the help of native method. This method will return the Dictionary or Array (Depending on your server response.)
I really need a code for send and receive data from server with JSON, i find a really good code but it isn't compatible with iOS9.
#IBAction func submitAction(sender: AnyObject) {
//declare parameter as a dictionary which contains string as key and value combination.
var parameters = ["name": nametextField.text, "password": passwordTextField.text] as Dictionary<String, String>
//create the url with NSURL
let url = NSURL(string: "http://myServerName.com/api") //change the url
//create the session object
var session = NSURLSession.sharedSession()
//now create the NSMutableRequest object using the url object
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST" //set http method as POST
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &err) // pass dictionary to nsdata object and set it as request body
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
//create dataTask using the session object to send data to the server
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume() }
Really thanks for the help
Swift syntax changed a little bit, but not significantly to break the whole code.
You will need to adjust few things like
println(err!.localizedDescription)
to
print(err!.localizedDescription)
Then your code will compile
Maybe have a look into the Alamofire Framework.
It really is making your life easier when it comes to handling HTTP requests.
Otherwise, as vadian suggested, check out the Swift 2 (do-try-catch) Errorhandling.
I have found a great tutorial Project from deege.
https://github.com/deege/deegeu-swift-rest-example
Here a breakdown of a HTTP request.
// Setup the session to make REST GET call. Notice the URL is https NOT http!! (if you need further assistance on how and why, let me know)
let endpoint: String = "https://yourAPI-Endpoint"
let session = NSURLSession.sharedSession()
let url = NSURL(string: endpoint)!
// Make the call and handle it in a completion handler
session.dataTaskWithURL(url, completionHandler: { ( data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
// Make sure we get an OK response
guard let realResponse = response as? NSHTTPURLResponse where
realResponse.statusCode == 200 else {
print("Not a 200 response")
return
}
// Read the JSON
do {
if let jsonString = NSString(data:data!, encoding: NSUTF8StringEncoding) {
// Print what we got from the call
print(jsonString)
// Parse the JSON
let jsonDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
let value = jsonDictionary["key"] as! String
}
} catch {
print("bad things happened")
}
}).resume()
I am using the following code in my swift 2.0 project. I cannot add Alamofire.request though I added "import Alamofire". I have to create object of Alamofire and then access through it.
This is how I create the object :
let manager = Alamofire.Manager.sharedInstance
manager.request(NSURLRequest(URL: NSURL(string: "http://httpbin.org/get")!))
let parameters = ["foo": "bar"]
manager.request(.POST, "url", parameters: parameters)
.responseJSON { request, response, json, error in
print("request: \(request)")
}
I am new to both Alamofire and swift. Can anybody tell how can I get response from the above code in a completion handler and why I cannot use Alamofire.request instead of manager.request.
Please see my Post method and Hope It helps
Post Method:
/**
** POST Method for calling API
* Services gateway
* Method get response from server
* #parameter -> requestObject: request josn object ,apiName: api endpoint
* #returm -> void
* #compilationHandler -> success: status of api, response: respose from server, error: error handling
**/
static func getDataWithObject( requestObject: NSDictionary, apiName : NSString,
completionHandler:
(success : Bool, response : NSDictionary, error : ErrorType?) -> Void) {
// Make Url
let url = NSURL(string: apiName as String)
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
//request.setValue("application/json", forHTTPHeaderField: "Content-Type")
// Call the method to request and wait for the response
// #param ->
// #return ->
Alamofire.request(.POST, url!, parameters:requestObject as? [String : AnyObject], encoding: .JSON)
.responseJSON {responseRequest, responseResponse, responseResult in
// Switch for Success or Error
switch responseResult {
// If the API return succesfull response
case .Success(let data):
let data_ar = data as! NSDictionary
print(data_ar)
// Get the Status if 0 then error if 1 then succes
// From our server side
if let str = data_ar.valueForKey("OK") as? Bool {
// Check if the status is OK and no error from
// our server side
if ( str ) {
print("Response from Server %#", data_ar)
// Cast the response and pss to handler
// To notify
completionHandler(success: true, response:data_ar
, error:responseResult.error )
} else {
print("Error from Our Server %#", data_ar)
let str = data_ar.valueForKey("message") as! NSString
self.showAlertView(str, title: "Error From Server")
}
}
case .Failure(let data, let error):
print("Request failed with error: \(error)")
print(data)
print((error as! NSError).localizedDescription)
self.showAlertView((error as! NSError).localizedDescription, title: "Error From Server")
}
}
}
Request not always in JSON please check your request :
Following are examples to use Alamofire with the Swift 2 :
GET - JSON
Alamofire.request(.GET, "http://api.androidhive.info/contacts/", parameters: nil, encoding: .JSON, headers: nil).responseJSON { (req, res, json) -> Void in
print("\(res?.allHeaderFields)")
print("\(json.value!)")
}
POST - without JSON
Alamofire.request(.POST, "http://httpbin.org/get", parameters: ["foo": "bar"], encoding: .URL, headers: nil).response { (req, res, data, error) -> Void in
print(res)
print(data)
let dataString = NSString(data: data!, encoding:NSUTF8StringEncoding)
print(dataString)
}
I need to upload an image to the server endpoint where the structure has to be as following:
{ "image": { "file": imageData }, "access_token": access_token }
How can I send such a request using NSURLSession (or maybe even Alamofire or AFNetworking)?
You cannot just include binary image data in a JSON request. JSON requires text representation, so if you do this, you must convert it to string (e.g. base64 encoding), use that in the JSON, and then the server code would presumably convert the base64 string back to binary data before attempting to use it.
But if you were base64 encoding of the image, it might look something like:
// get image data
let imageData = UIImagePNGRepresentation(image)
// convert to base64
let base64String = imageData.base64EncodedStringWithOptions(nil)
// build parameters
let parameters = ["image": ["file" : base64String], "access_token" : accessToken]
// get JSON
var error: NSError?
let data = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &error)
assert(data != nil, "Unable to serialize \(error)")
// build request
let url = NSURL(string: "http://example.com/upload")!
let request = NSMutableURLRequest(URL: url)
request.addValue("text/json", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
let task = NSURLSession.sharedSession().uploadTaskWithRequest(request, fromData: data) { data, response, error in
// check for basic connectivity errors
if error != nil {
println("error: \(error)")
return
}
// check for server errors
if let httpResponse = response as? NSHTTPURLResponse, let statusCode = httpResponse.statusCode as Int? {
if statusCode != 200 {
println("status code is \(statusCode)")
}
}
// check for details of app-level server response, e.g. if JSON that was dictionary:
var parseError: NSError?
if let responseObject = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &parseError) as? [String : AnyObject] {
println(responseObject)
} else {
println("JSON parse failed: \(parseError)")
println("response was: \(response)")
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("responseString was: \(responseString)")
}
}
task.resume()
If you use Alamofire, this is simplified:
// build parameters
let parameters = ["image": ["file" : base64String], "access_token" : accessToken] as [String : AnyObject]
// build request
let urlString = "http://example.com/upload"
Alamofire.request(.POST, urlString, parameters: parameters, encoding: .JSON)
.responseJSON(options: nil) { request, response, responseObject, error in
if error != nil {
println(error)
} else {
println(responseObject)
}
}
But both of the above are making assumptions about the nature of the response, that the server is base64 decoding the image data from the JSON, etc., but hopefully this illustrates the basic patterns.
Alternatively, use an application/x-www-form-urlencoded request, in which you can send binary data as illustrated here.
Found a solution using AFNetworking with help from https://stackoverflow.com/a/11092052/3871476
For others looking for the solution.
let manager = AFHTTPRequestOperationManager(baseURL: NSURL(string: url))
let request = manager.POST(url, parameters: param, constructingBodyWithBlock: {(formData: AFMultipartFormData!) -> Void in
formData.appendPartWithFileData(imgdata, name: "image[file]", fileName: "photo.jpeg", mimeType: "image/jpeg")
}, success: {(operation: AFHTTPRequestOperation!, responseObject: AnyObject!) -> Void in
//Success
}, failure: {(operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
//Failure
println(error.localizedDescription)
})
The trick was to use the "image[file]" parameter.
Try this:
var request = NSMutableURLRequest(URL: NSURL(string: "https://\(IP):\(port)/")!)
var response: NSURLResponse?
var error: NSError?
//Adding the JSON String in HTTP Body
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(jsonString, options: nil, error: &error)
request.timeoutInterval = (number as! NSTimeInterval)
request.HTTPMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("gzip", forHTTPHeaderField: "Accept-encoding")
let urlData = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)