Alamofire garbage at end error while parsing json - ios

I'm connecting to my server on localhost to fetch some data. The data returned to this request is a JSON, on Postman the JSON is correctly shown, but when I'm playing with iOS, Alamofire returns me an error:
responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error
Domain=NSCocoaErrorDomain Code=3840 "Garbage at end."
UserInfo={NSDebugDescription=Garbage at end.}))
The JSON in question is:
{
"name": "TestName",
"surname": "TestSurname"
}
The thing that I do not understand is that if I force my server to return the json in form of a string so something like
"{"name": "TestName after update","surname": "TestSurname"}"
Alamofire does not complain and parses it correctly. How is that? I thought that specifying the parameter responseJSON it would have worked the other way around.
Alamofire.request("http://192.168.1.4:8080/user/abcdf").validate().responseJSON { response in
switch response.result {
case .success:
// DO stuff
case .failure(let error):
print(error)
}
}

This means your API response string is not a proper JSON. Ensure your response is valid JSON. In my case (below), JSON String had some HTML characters which broke the JSON.
If you are using Alamofire, change .responseJSON to .responseString and verify the response structure is valid JSON.
Note : if you are using Postman, you may not notice the extra unwanted character in JSON response. You need to change the response type from "Pretty" to "Raw" to observe this.

I think you need to get the data so you should have it written like this I am not sure though
Alamofire.request("http://192.168.1.4:8080/user/abcdf",method:.get).responseJSON {
response in
if response.result.isSuccess {
//do stuff
}
else {
// do other stuff
}
}

Related

Alamofire: Parameters not being passed to server

This is my first time trying to use Alamofire so please forgive me if this is a glaring oversight! I've read a lot of the other answers and have made a lot of tweaks, but nothing seems to work.
I am trying to do a really simple test where a parameter is passed from an iOS app to the server, which checks if it is equal to "Test" and if so, returns some json data back to the iOS app.
Although the debugPrint method outputs SUCCESS, the json data printed by the iOS app is always "Not set", implying that the parameters haven't actually been passed to the php file. I was wondering if someone could help me out!
At the moment I'm not too concerned about parsing the json, but am just trying to figure out the cause of the lost parameter! Thanks in advance.
Here is my PHP:
<?php
$name = $_POST["name"];
if (isset($name))
{
if($name == "Test"){
echo json_encode("Correct");
}
else
{
echo json_encode("Incorrect");
}
}else{
echo json_encode("Not set");
}
?>
And here is my swift code:
let url = "http://mywebsite.com/xxx.php"
let parameters: [String:String] = ["name":"Test"]
Alamofire.request(url, method: .post, parameters: parameters, encoding: URLEncoding.default).responseJSON{ response in
debugPrint(response)
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
else {
print(response.result.error!)
}
}
Change URLEncoding.default to JSONEncoding.default.
Setting encoding to URLEncoding.default will pass params via query string.
(i.e. http://mywebsite.com/xxx.php?name=test).
Also change $POST_ with $_POST

Alamofire post request returning "<?xml version="1.0" encoding="utf-8"?>"

Using swift 4, I am doing a post request to a web api. The api has correct JSON data but whenever i call it is returning the following response: 
<?xml version="1.0" encoding="utf-8"?>
My code is:
let urlString = "XXXXXXXXXX/ArticlesByListofIds"
Alamofire.request(urlString, method: .post, parameters: ["ids": "160, 145"],encoding: JSONEncoding.default, headers: nil).responseString { response in
switch response.result {
case .success(let responseString1):
print("the response is: \(responseString1)")
break
case .failure(let error):
print("The error is: \(error)")
}
}
Any idea why is this happening?
I see two things happening. First, the API seems to respond with XML rather than JSON, so probably your request is not what you intended it to be. Second, there seems to be an issue with character encoding. This could be anything; maybe a fault in the server configuration, maybe you are decoding the file incorrectly.

Return JSON result of Alamofire request from function Using Swift 4

I have a function that returns the JSON result from the alamofire request. Initially the idea was to retrieve one of the values from the JSON result and store these in the array but each time I try to return either the JSON result or the populated int array, I get an empty result at the end of the function. The request is:
func getSeats()-> JSON{
var json : JSON = JSON()
Alamofire.request(url , method: .get)
.responseJSON{
response in
switch response.result {
case .success:
json = JSON(response.result.value!)
case .failure:
KRProgressHUD.showError(withMessage: "Could not retrieve reserved seats")
}
}
return json
}
Initially, looking at the AlamoFire documentation, I tried to make use of the option of returning an array from the json result so I modified my code like this:
func getSeats()-> [Int]{
var json : JSON = JSON()
Alamofire.request(url , method: .get)
.responseJSON{
response in
switch response.result {
case .success:
json = JSON(response.result.value!)
case .failure:
KRProgressHUD.showError(withMessage: "Could not retrieve reserved seats")
}
}
return json.arrayValue.map { $0["seat_no"].intValue }
}
But this also returned an empty array which is why I had to change the function. The format of the JSON I receive is as follows:
[
{
"id": 1,
"bus_id": 11,
"seat_no": 6,
"arrived_at": "2018-01-16 20:58:57"
},
{
"id": 2,
"bus_id": 11,
"seat_no": 27,
"arrived_at": "2018-01-16 21:40:29"
}
]
I am very new to Swift and this is taking me forever to understand and work it out.
Your functions are returning the empty json variable before it actually gets set to JSON(response.result.value!). You shouldn't be returning the json like that, or anything at all really. Your function should take a closure argument instead, and the closure argument itself can take your json argument. Then you can execute the closure when you get the response back from the server and just pass it the parsed json.
I would recommend learning more about synchronous vs. asynchronous programming. Networking is asynchronous by default and it takes time for the data you're requesting to actually return in a response from the server.
Go research basic asynchronous programming, and networking with closures and completion blocks. Any basic iOS networking tutorial will cover these things.

compare error object return by alamofire

I'm using Alamofire with EVReflection, in case responseObject fails to parse the raw response string into an object, an response.error will have some value, in case of a different error, a different value will be set.
Not sure how to compare those error values, to handle different error.
in case of JSON parsing error, print(error) will output
FAILURE: Error Domain=com.alamofirejsontoobjects.error Code=1 "Data could not be serialized. Input data was not json." UserInfo={NSLocalizedFailureReason=Data could not be serialized. Input data was not json.}
Alamofire.request(...)
.responseObject { (response: DataResponse<UserData>) in
guard response.error == nil else {
print(response.error)
return
}
}
When your request fails, you will get an error of type AFError from Alamofire. You can actually check AFError.swift file to get familiar with possible values. This file have really good documentation for every case.
Since AFError is an Error, which is of type enum, you can check like following:
switch err {
case .parameterEncodingFailed(let reason):
// do something with this.
// If you want to know more - check for reason's cases like
// switch reason {
// case .jsonEncodingFailed(let error):
// … // handle somehow
// case .propertyListEncodingFailed(let error):
// … // handle somehow
// }
case .responseValidationFailed(let reason):
// do something else with this
…
}
And for every reason you have some helper functions, so you can get even more info. Just check documentation.

Printing data in Alamofire request

I am trying to print the data returned from an alamofire post request in swift like so:
Alamofire.request(.POST, "http://blablabla.com/test1", parameters: ["operand1": "123"]).response { request, response, data, error in
print(request)
print(response)
print(data, radix: 16)
print(error)
}
but when I try to print data it doesn't print a string a string, instead it prints:
<796570>
I am a bit new to swift so I don't really know if there is a way or a reason for this.
That is the raw server response which is in NSData type. You can make use of some built-in serializers such as .responseString() in order to convert that into user readable value:
Alamofire.request(.POST, "http://blablabla.com/test1", parameters: ["operand1": "123"]).responseString { response in
print("Response String: \(response.result.value)")
}
You can check out other serializers in the Alamofire documentation.

Resources