vipulk617 vipulk617 - 5 months ago 139
Swift Question

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.

Answer

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:

enum JSONError: String, ErrorProtocol {
    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
    }
    let request = URLRequest(url: endpoint)
    URLSession.shared().dataTask(with: request) { (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()
}