Alamofire JSON response with strange characters in Swift - swift

I'm using Alamofire 3.0 and swift 2 and get a strange response from the following request:
func requestURLwithHeadersAndParams(URLstr:String, connectionMethod: Alamofire.Method, header: [String : String], body:[String : AnyObject], completion: (reponse: String, statusCode: Int, error: String) -> Void) {
///Singleton Alamofire connection manager
let alamofireManager = Alamofire.Manager.sharedInstance
alamofireManager.request(connectionMethod, URLstr, parameters: body, encoding: ParameterEncoding.JSON, headers: header).responseJSON (){
response in
print("\nSuccess: \(response.result.isSuccess)")
switch response.result {
case .Success(let value):
print("Response Status code: \((response.response?.statusCode)!)\n")
print("\(value)")
completion(reponse: "\(value)" , statusCode: (response.response?.statusCode)! , error: "")
case .Failure(let error):
print("Error Code:\(error.code) - Description:\(error.localizedDescription)")
completion(reponse: "Error" , statusCode: (response.response?.statusCode)!, error: error.localizedDescription)
} } }
the value property contains:
"{\n \"auth_token\" = \"qcW-mQmyX8ototieJu7WK\";\n avatar = {\n standard = {\n url = \"<null>\";\n };\n url = \"<null>\";\n };\n birthdate = \"<null>\";\n \"created_at\" = \"2015-10-28T07:02:20.445Z\";\n email = \"elrope#abt.com\";\n \"first_name\" = El;\n id = 12;\n \"last_name\" = Perro;\n role = user;\n \"shooter_type\" = \"\";\n \"updated_at\" = \"2015-10-28T07:42:37.860Z\";\n}"
any idea how can I get rid of all the escape characters ('\' and '\n') since the JSON serialization using SwiftyJSON in the method calling this method can't recognize the string as a json string and fails when I do let json = JSON(reponse) with error:
Error Domain=SwiftyJSONErrorDomain Code=901 "Dictionary["auth_token"]
failure, It is not an dictionary" UserInfo=0x6030002d7c00
{NSLocalizedDescription=Dictionary["auth_token"] failure, It is not an
dictionary})

I found your JSON invalid itself.
e.g. avatar, standard are not strings, where are the quotes?
I belevie using , and : is better practice than using ; and =
I tested on SwiftyJSON and after above changes everything works fine. So maybe the issue is on your backend. Try to validate raw JSON using web browser.

Your JSON is invalid.
Actually, your value string is nothing else than the .description output of an NSDictionary!
Demonstration in a Playground:
Needless to say that this isn't JSON... so of course it fails when you try to give this to SwiftyJSON.
So, either you were confused somewhere and you're using your dictionary's description instead of its actual content...
...or this error comes from the server.

Related

Alamofire, Swift: What could be causing this error?

What could be causing this error?
All of a sudden out of nowhere I started getting the error below. I have reinstalled the cocoapod, cleaned the build folder, and reinstalled the app already and none of that has fixed the error.
ERROR: Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
CODE:
let recoverUrl = "http://www.website.com/recover.php?email=\(emailData)&local=application"
let urlEncodedString = recoverUrl.replacingOccurrences(of: " ", with: "%20")
parseRecover(url: urlEncodedString)
//////////////
func parseRecover(url : String){ AF.request(url).responseJSON(completionHandler: { response in self.parseData(JSONData: response.data!) }) }
func parseData(JSONData : Data){
do {
var readableJSON = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! JSONObject
if let recoverJSON = readableJSON["Recover"] as? [JSONObject] {
for i in 0..<recoverJSON.count {
let JSON = recoverJSON[i]
let status = JSON["status"] as! String
let message = JSON["message"] as! String
if status == "Error" {self.Alert01("\(message)")}
else if status == "Success" { self.Alert02("\(message)") }
}}}
catch { print(error) }
}
ERROR IS OCCURING AT:
func parseRecover(url : String){ AF.request(url).responseJSON(completionHandler: { response in self.parseData(JSONData: response.data!) }) }
There's no guarantee that a response has data, so force unwrapping the value can lead to crashes. I suggest you create Decodable types to parse your responses and use Alamofire's responseDecodable method to handle your responses.
Additionally, even if you don't adopt Decodable, responseJSON already parses your response Data using JSONSerialization, so you can just access the response.result to see the output.
SOLVED: The issue was within my php file. I was using $_GET[''] and it should have been a $_POST[''] or $_REQUEST['']

Print data from Alamofire request, swift

I made this request:
func AlamofireGetCode()
{
let username: String = searchTextField.text!
var url:String!
url = "https:// ... "
AF.request(url, method: .get, encoding: JSONEncoding.default)
.responseJSON { response in
switch response.result {
case .success:
debugPrint(response)
case .failure(let error):
fatalError("\(error)")
}
}
}
And I'm getting this response with different fields:
[Result]: success({
"incomplete_results" = 0;
items = (
{
"username" = " ... "
...
How do I get some specific field like "username" in Swift?
I would like to have all the username of all the user and store them, could you help me?
You need to provide a type to parse the JSON response into. Using a site like quicktype.io can generate one from your JSON, but any Decodable type will do. Then you can use Alamofire's responseDecodable handler to parse your response.
AF.request(url).responseDecodable(of: TypeToParse.self) { response in
debugPrint(response)
}
Paste your response in https://jsonparseronline.com/ to see the structure of the object. It will show you all the keys and values that you can access using subscripts.

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])
}
}

Cloudant function-clause error at HTTP GET request

This is my first question here and I have not much experience in coding so please bear with me. Thanks!
I defined some documents in my Bluemix Cloudant account with different cars which have different characteristics. I want to get one entry from an IOS Swift front-end App.
This is an example query url:
https://$ACCOUNT-bluemix.cloudant.com/cars/_design/car_index/_search/car_index_name?q=size:small
Now the problem: If I use this url in a browser I get the correct results in JSON format back without any error. But if the app makes the request a function-clause error is logged while the request itself seems to be successful.
I read that a function_clause error is caused by some bug in the Javascript Cloudant uses for indexing the documents. The Javascript I'm using is exactely the same as Cloudant states it in the tutorials.
Has anyone an idea why it works in the browser but not in the App?
Thank you very much for any help!
Here is all the code:
This is the method I use in swift to make the request:
func databaseRequest(size: String, interior: String, fuel: String) {
let baseURL = "https://$ACCOUNT-bluemix.cloudant.com/cars/_design/car_index/_search/car_index_name?q="
let queryURL = "size:\(size)"
let completeURL: String = baseURL + queryURL
let completeURLModified = completeURL.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
let requestURL = URL(string: completeURLModified!)
var request = URLRequest(url: requestURL!)
request.httpMethod = "GET"
request.setValue("Basic \(credentials)", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request){data, response, error in
guard error == nil else{
print("There was an error:", error as Any)
return
}
guard data == data else{
print("Data is empty")
return
}
let jsonResponse = try! JSONSerialization.jsonObject(with: data!, options: [])
print("This is JSON Response", jsonResponse)
}; task.resume()
}
This is the response from the JSON answer:
This is JSON Response {
error = "unknown_error";
reason = "function_clause";
ref = 1944801346;
}
The rest of log from http headers if this is helpful:
Optional(<NSHTTPURLResponse: 0x6080000349c0> { URL: https://$ACCOUNT-bluemix.cloudant.com/cars/_design/car_index/_search/car_index_name?q=size:small } { status code: 500, headers {
"Cache-Control" = "must-revalidate";
"Content-Length" = 70;
"Content-Type" = "application/json";
Date = "Thu, 24 Nov 2016 04:41:03 GMT";
Server = "CouchDB/2.0.0 (Erlang OTP/17)";
"Strict-Transport-Security" = "max-age=31536000";
Via = "1.1 lb1.bm-cc-dal-01 (Glum/1.31.3)";
"X-Cloudant-Backend" = "bm-cc-dal-01";
"X-Content-Type-Options" = nosniff;
"X-Couch-Request-ID" = 51e5e0b5e1;
"X-Couch-Stack-Hash" = 1944801346;
"X-CouchDB-Body-Time" = 0;
Last but not least the Javascript file I use as Index in the design document in Cloudant:
function (doc) {
index("name", doc.name, {"store": true});
if (doc.fuel){ index("fuel", doc.fuel, {"store": true});}
if (doc.interior){ index("interior", doc.interior, {"store": true});}
if (doc.size){index("size", doc.size, {"store": true});
}}
I think this error is due to cloudant trying to decode whatever you passed as \(credentials) as a base64 encoded string. If \(credentials) is not a valid base64 encoded string (e.g. contains characters other than a-z, A-Z, 0-9, +, / and =), then my guess is that cloudant's base64 decoding function fails with the above error.
You need to make sure that \(credentials) is the string <your_username>:<your_password> encoded correctly. E.g. if your username is john and your password is doe, then \(credentials) should be am9objpkb2U=.

NSJSONSerialization error. Code=3840 "Invalid value around character 0

NSJSONSerialization.JSONObjectWithData error when using a string like "abc" but success using "123"
I do not know why.
error log
2015-11-04 17:42:02.997 SwiftJsonDemo[27196:2701028] Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}
code
//var str = "123" // ok
var str = "abc" // error
let strData = str.dataUsingEncoding(NSUTF8StringEncoding)
if let d = strData {
let urlStr = String(data: d, encoding: NSUTF8StringEncoding)
do {
let json = try NSJSONSerialization.JSONObjectWithData(d, options: NSJSONReadingOptions.AllowFragments)
} catch let e {
print(e)
}
} else {
print("data error")
}
123
is a valid JSON number, so this can be read as JSON if the .AllowFragments
option is set. JSON strings must be enclosed in quotation marks:
(see http://www.json.org for the details):
"abc"
In a Swift string literal, these quotation marks are escaped with
backslashes:
let str = "\"abc\"" // OK!
let strData = str.dataUsingEncoding(NSUTF8StringEncoding)
// ...
Check with following line of code if using swift:
let contentType = response.response?.allHeaderFields["Content-Type"] as? String
Content type will be not coming as: "application/json". It implies response from server is not a valid JSON string.
Please check Response in Postman. i just solved by checking if json response is proper format or in html format
I got the same error. Turns out the mistake is in the request. The below syntax fixed the problem while adding parameters to the request.
request.setValue("Value", forHTTPHeaderField: "Key")