How to parse JSON in Swift using NSURLSession

I am trying to parse JSON but getting this error:

type of expression is ambiguous without more context

My code is:

func jsonParser() {

    let urlPath = "http://headers.jsontest.com/"
    let endpoint = NSURL(string: urlPath)
    let request = NSMutableURLRequest(URL:endpoint!)

    let session = NSURLSession.sharedSession()
    NSURLSession.sharedSession().dataTaskWithRequest(request){ (data, response, error) throws -> Void in

        if error != nil {
            print("Get Error")
        }else{
            //var error:NSError?
            do {
                let json:AnyObject =  try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(rawValue: 0)) as? NSDictionary

            print(json)

        } catch let error as NSError {
            // error handling
            print(error?.localizedDescription)
        }
        }
    }
    //task.resume()
}

This is working fine with out try catch in Xcode 6.4 but this is not working in Xcode 7.


Solution 1:

Don't declare an AnyObject type for your decoded object since you want it to be an NSDictionary and you're performing a conversion to do this.

Also it's better to use zero options for NSJSONSerialization instead of random ones.

In my example I've also used a custom error type just for demonstration.

Note, if you're using a custom error type, you have to also include a generic catch to be exhaustive (in this example, with a simple downcasting to NSError).

enum JSONError: String, ErrorType {
    case NoData = "ERROR: no data"
    case ConversionFailed = "ERROR: conversion from JSON failed"
}

func jsonParser() {
    let urlPath = "http://headers.jsontest.com/"
    guard let endpoint = NSURL(string: urlPath) else {
        print("Error creating endpoint")
        return
    }
    let request = NSMutableURLRequest(URL:endpoint)
    NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) in
        do {
            guard let data = data else {
                throw JSONError.NoData
            }
            guard let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary else {
                throw JSONError.ConversionFailed
            }
            print(json)
        } catch let error as JSONError {
            print(error.rawValue)
        } catch let error as NSError {
            print(error.debugDescription)
        }
   }.resume()
}

The same with Swift 3.0.2:

enum JSONError: String, Error {
    case NoData = "ERROR: no data"
    case ConversionFailed = "ERROR: conversion from JSON failed"
}

func jsonParser() {
    let urlPath = "http://headers.jsontest.com/"
    guard let endpoint = URL(string: urlPath) else {
        print("Error creating endpoint")
        return
    }
    URLSession.shared.dataTask(with: endpoint) { (data, response, error) in
        do {
            guard let data = data else {
                throw JSONError.NoData
            }
            guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary else {
                throw JSONError.ConversionFailed
            }
            print(json)
        } catch let error as JSONError {
            print(error.rawValue)
        } catch let error as NSError {
            print(error.debugDescription)
        }
    }.resume()
}

Solution 2:

Apple declare here.

func dataTaskWithRequest(request: NSURLRequest, completionHandler: (NSData?, NSURLResponse?, NSError?) -> Void) -> NSURLSessionDataTask

Fix it:

NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in
       // Your handle response here!
}

UPDATE:

func jsonParser() {
    let urlPath = "http://headers.jsontest.com/"
    let endpoint = NSURL(string: urlPath)
    let request = NSMutableURLRequest(URL:endpoint!)

    NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in
        print(error)
    }.resume()
}

RESULT:

Optional(Error Domain=NSURLErrorDomain Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." UserInfo={NSUnderlyingError=0x7f8873f148d0 {Error Domain=kCFErrorDomainCFNetwork Code=-1022 "(null)"}, NSErrorFailingURLStringKey=http://headers.jsontest.com/, NSErrorFailingURLKey=http://headers.jsontest.com/, NSLocalizedDescription=The resource could not be loaded because the App >Transport Security policy requires the use of a secure connection.})

Hope this helps!

Solution 3:

For Swift 4 Web service Call , Post Method using URLSession

 func WebseviceCall(){
        var request = URLRequest(url: URL(string: "YOUR_URL")!)
        request.httpMethod = "POST"
        let postString = "PARAMETERS"
        request.httpBody = postString.data(using: .utf8)
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json", forHTTPHeaderField: "Accept")

        let task = URLSession.shared.dataTask(with: request) { data, response, error in

            guard let data = data, error == nil else {
                print("error=\(error)")
                return
            }

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(response)")
            }

            do {
                if let convertedJsonIntoDict = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary {
                    // Print out dictionary
                    print(convertedJsonIntoDict)
               }
            } catch let error as NSError {
                print(error.localizedDescription)
            }
        }
        task.resume()
    }