Alamofire: How to custom response serialization

Created on 13 Oct 2015  路  4Comments  路  Source: Alamofire/Alamofire

I use Alamofire-beta3, I want to custom response serialization, but I get a error "Cannot call value of non-function type 'NSHTTPURLResponse?' "

image

My code is below:

 public static func objectSerializer <T: MTLModel> () -> ResponseSerializer <T, MTLError>  {

    return ResponseSerializer <T, MTLError> { request, response, data, error in

        // Http Error with Http status code
        guard error == nil else {
            let failureReason = "Network Error"
            let error = MTLError.errorWithCode(error!.code, failureReason: failureReason)
            return .Failure(error)
        }

        // data be null
        guard let validData = data where validData.length > 0 else {
            let failureReason = "JSON could not be serialized. Response data was nil or zero length."
            let error = MTLError.errorWithCode(.ResponseDataNull, failureReason: failureReason)
            return .Failure(error)
        }

        do {
            let JSON = try NSJSONSerialization.JSONObjectWithData(validData, options: .AllowFragments)

            // response data is not a obejct json
            guard let json = JSON as? [String : AnyObject] else {
                let failureReason = "JSON could not be serialized. Response data is not a obejct JSON"
                let error = MTLError.errorWithCode(.JSONSerializeToObjectFailed, failureReason: failureReason)
                return .Failure(error)
            }

            // Http request successful(state 200 OK), but response data not include `Error Section`
            guard let errorDict = json["error"] as? [String : AnyObject] else {
                let failureReason = "JSON could not be serialized. Http request successful(state 200 OK), but response data not include `Error Section`"
                let error = MTLError.errorWithCode(.JSONSerializeErrorSectionFailed, failureReason: failureReason)
                return .Failure(error)
            }

            // mean request failed
            if errorDict.count != 0 {

                let error: MTLError!
                do {
                    error = try MTLJSONAdapter.modelOfClass(MTLError.self, fromJSONDictionary: errorDict) as! MTLError
                } catch _ {
                    let failureReason = "MTLError object serialize failed"
                    error = MTLError.errorWithCode(.JSONSerializationFailed, failureReason: failureReason)
                }
                return .Failure(error)

            } else {
                // mean request successful
                let dataDict = json["data"] as? [String : AnyObject]

                do {
                    let object = try MTLJSONAdapter.modelOfClass(T.self, fromJSONDictionary: dataDict) as! T
                    return .Success(object)
                } catch _ {
                    let failureReason = "\(T.self) object serialize failed"
                    let error = MTLError.errorWithCode(.JSONSerializationFailed, failureReason: failureReason)
                    return .Failure(error)
                }
            }

        } catch _ {
            let failureReason = "Network Error"
            let error = MTLError.errorWithCode(error!.code, failureReason: failureReason)
            return .Failure(error)
        }

    }
}


  public func responseObject<T: MTLModel> (queue: dispatch_queue_t? = nil, willStart: (() -> Void)? = nil, didStop: (() -> Void)? = nil, completionHandler: Response<T, NSError> -> Void) -> Self
{
    willStart?()
    UIApplication.sharedApplication().networkActivityIndicatorVisible = true

    return response(responseSerializer: Request.objectSerializer(), completionHandler: { (response: Response<T, NSError>) in

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in

            self.printResponse(response)

            dispatch_async(queue ?? dispatch_get_main_queue()) {
                didStop?()
                UIApplication.sharedApplication().networkActivityIndicatorVisible = false
                completionHandler(response)
            }

        })
    })
}

I have see #817 , but I still don't know how to change my code. Please help me.

response serializer support

Most helpful comment

@cnoon it would be epic if you can add some blog post or improved documentation about customer serializers. Its quite hard to implement for those of us learning, and the various articles on the internet seem to have wildly different ways of implementing it.
Can we have one siimple way as an example that doesn't rely on 3rd party libaries and just shows the basics?

All 4 comments

First, please update to the release version of Alamofire 3 so we can rule out an issue with the older version.

Second, your definition of the response serializer, public static func objectSerializer() -> ResponseSerializer needs to include the types of the value and error to be returned. It's likely that by adding those your code will build successfully.

Now I have updated to the release version of Alamofire 3, but still build error.
the response serializer public static func objectSerializer<T: MTLModel>() -> ResponseSerializer<T, MTLError> return the types <T, MTLError>
The code above no return the types of the value and error ?

Here's a much more condensed version of your logic that compiles fine on Alamofire 3.0.0:

protocol MTLModel {}
typealias MTLError = NSError

extension Request {
    static func objectSerializer <T: MTLModel> () -> ResponseSerializer <T, MTLError>  {

        return ResponseSerializer <T, MTLError> { request, response, data, error in
            let failureError = NSError(domain: "", code: 0, userInfo: nil)
            return Result<T, MTLError>.Failure(failureError)
        }
    }

    func responseObject<T: MTLModel> (queue: dispatch_queue_t? = nil, willStart: (() -> Void)? = nil, didStop: (() -> Void)? = nil, completionHandler: Response<T, NSError> -> Void) -> Self {
//        willStart?()
//        UIApplication.sharedApplication().networkActivityIndicatorVisible = true

        return response(responseSerializer: Request.objectSerializer(), completionHandler: { (response: Response<T, NSError>) in

            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in

                print(response)

                dispatch_async(queue ?? dispatch_get_main_queue()) {
                    didStop?()
                    UIApplication.sharedApplication().networkActivityIndicatorVisible = false
                    completionHandler(response)
                }  
            })
        })
    }
}

If this doesn't end up working, please comment exactly why and I'll be happy to re-open.

@cnoon it would be epic if you can add some blog post or improved documentation about customer serializers. Its quite hard to implement for those of us learning, and the various articles on the internet seem to have wildly different ways of implementing it.
Can we have one siimple way as an example that doesn't rely on 3rd party libaries and just shows the basics?

Was this page helpful?
0 / 5 - 0 ratings