25

I had some working code that was getting results from a MySQL DB on a remote web server. It is no longer working and I keep getting the message responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength). Here is some code...

    Alamofire.request(ADS_URL, method: .get).validate().responseJSON { response in
        print("Request: \(String(describing: response.request))")   // original url request
        print("Response: \(String(describing: response.response))") // http url response
        print("Result: \(response.result)")                         // response serialization result

        switch response.result {
        case .success(let value):
            let json = JSON(value)
            print ("JSON: \(json)")

            if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
                print("Data: \(utf8Text)") // original server data as UTF8 string
            }

        case .failure(let error):
            print("Error while querying database: \(String(describing: error))")
            return
        }
    }

I am also using SwiftyJSON. Here are the results of the code...

Request: Optional(http://doyouado.com/adscan/get_ads)

Response: Optional(<NSHTTPURLResponse: 0x17502f3a0> { URL: http://doyouado.com/adscan/get_ads } { status code: 200, headers {
    Connection = "keep-alive";
    "Content-Length" = 0;
    "Content-Type" = "text/html; charset=UTF-8";
    Date = "Mon, 18 Sep 2017 16:04:37 GMT";
    Server = "nginx/1.12.1";
    "Set-Cookie" = "ado_session=a%3A5%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%225019d90891c70c81df8ebc2fe754a68f%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A15%3A%22109.150.214.128%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A86%3A%22ADoBroadcaster%2F1.0+%28com.GaryFrank.ADoBroadcaster%3B+build%3A1%3B+iOS+10.3.3%29+Alamofire%2F4.5.0%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1505750677%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3B%7D3130ef6f5541e6f944da5a5a1292350bf203fa1b; expires=Mon, 18-Sep-2017 18:04:37 GMT; Max-Age=7200; path=/";
} })

Result: FAILURE  

Error: responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength)

I have tried using .response and .responseString, but I get no information returned. I am completley stumped. This was all working fine. Hopefully there is someone that can shed some light on this?

iBug
  • 2,334
  • 3
  • 32
  • 65
gfgruvin
  • 435
  • 1
  • 4
  • 8
  • Are you sure the url points to a valid json? – Kyle Higginson Sep 18 '17 at 16:32
  • The URL is a php script that queries MySQL and returns the results as JSON. echo json_encode($ads); – gfgruvin Sep 18 '17 at 18:56
  • 1
    Try using `responseString` instead of `responseJSON` and print out `response.result.value` and see why it is not being able to serialize. You might be getting html or something. – boidkan Oct 04 '17 at 19:46
  • With responseString, an empty string is returned to response.result.value. If I put the URL in my browser, I can see the data in JSON format. I checked the JSON. It is valid. – gfgruvin Oct 13 '17 at 20:17
  • @boidkan thank you, it was useful for me! – iAleksandr Sep 10 '18 at 21:50

7 Answers7

16

Just simply change .responseJSON to .responseData.

And after this parse data:

let jsonDecoder = JSONDecoder() 
let parsedData = try jsonDecoder.decode(T.self, from: data)

and no error:

(Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength)
byouness
  • 1,746
  • 2
  • 24
  • 41
Igor Kruglik
  • 161
  • 1
  • 3
15

What worked for me was changing the encoding from JSONEncoding.default to URLEncoding.default!

Will Said
  • 394
  • 4
  • 7
  • For me, it was vice versa. Mine was a http-post request, i changed encoding from `URLEncoding.httpBody` to `JSONEncoding.default` – Ahmet Gokdayi Feb 27 '20 at 16:08
11

Updating from Alamofire 4 to 5 caused the issue in my case. By default, it seems that Alamofire 5 returns the error Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength for empty response body with status code 200. So adding 200 to the list of emptyResponseCodes resolved the issue for me:

request.responseData(emptyResponseCodes: [200, 204, 205]) { ... } // the default is [204, 205]
naydin
  • 345
  • 4
  • 5
5

What worked for me was changing from .responseData to .response

Asi Givati
  • 1,348
  • 1
  • 15
  • 31
0

Commonly this error comes when your API is 'GET' type and you pass 'POST' type.

The same problem I faced and my solution is I replace .post to .get and then this error removed.

For AFNetworking 3.0 :- go given path,

pods > Pods > AFNetworking > Serialization > AFURLResponseSerialization.m

then replace line no 228 (self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];)

with

self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", nil];

Because of your response in form of text/html but that is not mentioned in AFNetworking then we add it manually.

Note:- I debugging this problem for Alamofire.

Bijender Singh Shekhawat
  • 3,934
  • 2
  • 30
  • 36
0

When server sends back no response, Alamofire shows this message in the .failure block if you are printing the error message. Technically it is not an error. Alamofire didn't show this message in its earlier versions, but since one of the recent updates it started showing it.

As I said it is not really an error, but to me its a bug in Alamorfire. And it is very annoying and misleading to keep seeing this in your log when there is no error on your client or server side.

Here is how I silent it:

if (response.data?.count)! > 0 {print(error)}

And I do it when there is no response from the server, which is the expected behaviour since server is not supposed to send response in some cases.

Alamofire.request(MY_URL, method: .get, parameters: ["blabla": blablabla])
        .validate(statusCode: 200..<300)
        .responseJSON {
            response in
            switch response.result {
            case .success(let value):
                self.processResponse(value)
            case .failure(let error):
                if (response.data?.count)! > 0 {print(error)}
            }
    }

So the error message doesn't shows when nothing is returned from the server. In my opinion this should be the default behaviour.

zeeshan
  • 4,913
  • 1
  • 49
  • 58
0

Though the question is quite old, I wanted to provide to others what I recently discovered.

Since the error message is very generic and it doesn't help much, check that the url format you are using is correct. I've gotten this only to discover that the url format was incorrect. Once fixed things started working fine.

Micah Montoya
  • 757
  • 1
  • 8
  • 24