returning JSON as string in Swift using Swifty - swift

I'm using Alamofire and Swifty and am able to make my API POST and get data back successfully. However, I'm unsure of how to get the data that I'm printing and be able to return it as a string.
In the below, the println's print fine. However, when I use the same json["ticket"] as the return, I get 'JSON' is not convertible to 'Void'
let encoding = Alamofire.ParameterEncoding.URL
// Fetch Request
Alamofire.request(.POST, "http://api.co/?v=1", parameters: bodyParameters, encoding: encoding)
.validate(statusCode: 200..<300)
.responseJSON{(request, response, data, error) in
if (error == nil)
{
var json = JSON(data!)
println(json["ticket"])
return json["TOKEN"]
}
else
{
println("HTTP HTTP Request failed: \(error)")
}

The problem is you are returning "Dictionary" from the closure, while Closure return type is Void. So, you need to get that in a completion handler.
For better idea, you can take a look at this solution. Hope it helps!

Related

Alamofire iOS13

I want to update my code in the past when I used swift 2 or 3. I am stuck where I want to use Alamofire but the way to use it changed and I don't know how to use it anymore. Can anybody update this part of the code and explain a little bit? Thank you.
This is the original code.
Alamofire.request(.POST, url)
.response{ (request, response, data, error) in
let xml = SWXMLHash.parse(data!)
let sunsetTime = xml["result"]["rise_and_set"]["sunset_hm"].element?.text
self.sunsetTimeLabel.text = sunsetTime
self.getDateFromString(sunsetTime,year: comp.year,month: comp.month,day: comp.day)
if (error != nil) {
print(error)
}
}
this is the code I was writing.
AF.request(url, method: .post).responseJSON { (responseData) in
let xml = SWXMLHash.parse(responseData as Data)
let sunsetTime = xml["result"]["rise_and_set"]["sunset_hm"].element?.text
self.sunsetTimeLabel.text = sunsetTime
There is an error saying "Cannot convert value of type 'AFDataResponse' (aka 'DataResponse') to type 'Data' in coercion"
Your first code snippet is Alamofire 3 syntax. I infer from the second code snippet that you are now using Alamofire 5.
There are a few issues:
You are calling responseJSON (which you’d only use if your response was JSON, not XML). Use response or, better, responseData.
The response object passed to this closure is not a Data, itself. In the case of responseData method, it is a AFDataResponse object, which has a data property (which is a Data?). You have to extract the Data object from this AFDataResponse, either by unwrapping the contents of the data property, or from the result (see next point).
You should probably check for success or failure and extract the Data from the response.result object.
So, pulling this together, you end up with something like:
AF.request(url, method: .post).responseData { response in
switch response.result {
case .failure(let error):
print(error)
case .success(let data):
let xml = SWXMLHash.parse(data)
...
}
}

Alamofire and responseJSONDecodable with either Dictionary or Array type

I am working with Swift and Alamofire to access an API. I am using code similar to the following:
Almofire.request(url!, method: HTTPMethod.get, parameters: nil, encoding: JSONEncoding.default, headers: headers).validate() .responseJSONDecodable { (response: DataResponse<[GeoEntity]>) in
response.result.ifFailure({
let responseError = try? AUAPIError(response)
guard (responseError?.type == nil) else{
//if we get .InvalidGrant, get new token by logging in the normal way.
if (responseError?.type == .UnauthorizedClient){
AUService.shared.delegate?.unAuthorizedAccess(error: responseError!)
completion(nil, responseError)
}
return
}
})
response.result.ifSuccess({
completion(response.result.value, nil)
})
}
```
The problem I am facing is that DataResponse<[GeoEntity]> can either return an array of GeoEntity objects, or a single one as a dictionary. Using Alamofire 5 and responseJSONDecodable, how do I cater to both kinds that are returned. Or do I have to resort to the older way of decoding?
Please Check for type like
if response is NSArray{
//if type is array
}
if response is NSDictionary
{ //if type is Dictionary
}

Error 401: Alamofire/Swift 3

This code previously works, and suddenly after several works around it stopped and return an Error 401.
Alamofire.request(WebServices.URLS().TabDataURL, method: .post, parameters: reqParams).validate().responseJSON { response in
let statusCode = (response.response?.statusCode) //Get HTTP status code
guard response.result.isSuccess, let value = response.result.value else {
// FIXME:you need to handle errors.
print("Status, Fetching News List:", statusCode)
return
}
I have check via Postman, the parameters are correct. Infact, I can also login (by passing 2 parameters). But when I want to pull in a JSON data from server, I am getting 401.
my main project doesn't have an error. but instead of returning the JSON data, it gave me an Error 401. my other projects (same code format, same server & parameters) is giving me this error.
Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.} it worked!
Also, I have check with my other projects -- it seemed I cannot connect aswell. So I suspect it could be because of Alamofire, or my Xcode?
Anyone can help me?
Hi i think your server Response is not correct because, as error indicate object should not start with array same issue i come across tell backend developer to send response in dictionary,
{NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
let headers = [String: String]()// To add header if any
Alamofire.request(path,method: mType, parameters: parameters, encoding: JSONEncoding.default, headers : headers) .responseJSON
{ response in
//----- this code always works for me. & You don't need add header if not required.
if let JSON = response.result.value {
print("JSON: \(JSON)")
if response.response?.statusCode == 200
{
successCompletionHandler(JSON as! NSDictionary)
}
else if response.response?.statusCode == 401
{
failureCompletionHandler(JSON as! NSDictionary)
}
else
{
failureCompletionHandler(JSON as! NSDictionary)
}
}
else
{
print("error message")
failureCompletionHandler([WSAPIConst.ERROR:WSAPIConst.ERROR_MESSAGE])
}
}

RX Alamofire Swift empty response JSON

I am using Alamofire with rx and i'm having one issue that if the call is a success (status 200) there is no JSON returned. This triggers my error code. If I get status 400 I get JSON so the call is fine.
How do I specify that the response is JSON, but not to error if empty and status code 200?
Thanks!
func createUser(httpBody: AccountDetails!) -> Observable<(NSHTTPURLResponse, AnyObject)> {
return Alamofire.Manager.rx_request(.POST,
APIService.REGISTER_ENDPOINT,
parameters: httpBody.getParameters(),
encoding: .JSON,
headers: nil)
.flatMap {
$0
.validate(statusCode: 200..<501)
.validate(contentType: ["application/json"])
.rx_responseJSON()
.map { (response:NSHTTPURLResponse, object:AnyObject) -> (NSHTTPURLResponse, AnyObject) in
return (response, object)
}
}
}
EDIT:
I fixed this by changing .rx_responseJSON() to .rx_responseData() and returning NSData instead of AnyObject as the second parameter. Now the call succeeds and I manually convert the data to JSON. Not sure if this is the correct solution but it will suffice for now. Happy to hear better solutions though.
Thanks
I fixed this by changing .rx_responseJSON() to .rx_responseData() and returning NSData instead of AnyObject as the second parameter. Now the call succeeds and I manually convert the data to JSON. Not sure if this is the correct solution but it will suffice for now. Happy to hear better solutions though. Thanks
func createUser(httpBody: AccountDetails!) -> Observable<(NSHTTPURLResponse, NSData)> {
return APIManager.sharedManager.rx_request(.POST,
APIService.REGISTER_ENDPOINT,
parameters: httpBody.getParameters(),
encoding: .JSON,
headers: nil)
.flatMap {
$0
.validate(statusCode: [200,400,500])
.validate(contentType: ["application/json"])
.rx_responseData()
.map { (response:NSHTTPURLResponse, object:NSData) -> (NSHTTPURLResponse, NSData) in
return (response, object)
}
}
}

How can I retrieve the status message of a request made with Alamofire?

The server that I am using returns error messages in the HTTP status message. For example, it will return "400 User already exists" rather than "400 Bad Request".
I would like to access the string "User already exists" in the response method called by Alamofire. However, I cannot find any way to access this string.
I found this question on StackOverflow already: Swift Alamofire: How to get the HTTP response status code
Unfortunately, no one gives an answer to the question. :(
Here is where Chrome shows where the error is:
I would suggest trying to print out all the possible data fields that you are given and see what you can find. Please try the following example and see if that sheds any light.
let URL = NSURL(string: "your/url/to/somewhere")!
let parameters = ["foo": "bar"]
Alamofire.request(.POST, URL, parameters: parameters)
.response { request, response, data, error in
println("Request: \(request)")
println("Response: \(response)")
println("Error: \(error)")
if let data = data as? NSData {
println("Data: \(NSString(data: data, encoding: NSUTF8StringEncoding)!)")
}
}
Return response in json format from the server and then i think you'll be able to get the appropriate status.
I've implemented that thing using php codeigniter..from where my response is like
$response['status'] = 'user_already_exists';
$this->response($response, 400);
Now in swift you can go with this
Alamofire.request(.POST,URL, parameters:parameters) .responseJSON
{
(request, response, data, error) in
var json = JSON(data!) //I've used swiftyJSON for reading json response
let status = json["status"].stringValue
println("Status : \(status)")
}
Hope this may help you.