Reputation: 349
I have been trying to get a sample Rest request working on a sample swift iOS app I am working on. I have pulled from a few tutorials I have seen that said this works but my app seems to crash at
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
The exception is thrown in the swift_dynamicCast library. I can convert my response to a String without issues and the string is a valid json array. Any Ideas?
Here is the full code for my test function.
let url:NSURL = NSURL(string:"http://jsonplaceholder.typicode.com/comments")
let request:NSURLRequest = NSURLRequest(URL:url)
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var stringData :NSString = NSString(data:data, encoding:NSUTF8StringEncoding)
println(stringData)
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if(err?) {
println("JSON Error (err!.localizedDescription)")
}
println("AsSynchronous\(jsonResult)")
})
Upvotes: 3
Views: 4488
Reputation: 12383
Modified the above answer to work for the latest Swift 2.1 version and type casted to NSArray as mentioned above, it works and processes the json data
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL(string: "http://jsonplaceholder.typicode.com/comments")
// or use this http://jsonplaceholder.typicode.com/comments or this http://puppygifs.tumblr.com/api/read/json
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
if error != nil {
print(error)
} else {
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
// print(jsonResult)
print(jsonResult[0])
} catch {
print("my error")
}
}
})
task.resume()
}
}
Upvotes: 1
Reputation: 64674
As an addition to your own solution, you can use an if let
statement to make your casting more concise.
if let jsonResult: AnyObject = NSJSONSerialization.JSONObjectWithData(data,options:nil,error: nil) {
if let myDict = jsonResult as? NSDictionary {
println("myDict:\(myDict)")
}
else if let myArray = jsonResult as? NSArray {
println("myArray:\(myArray)")
}
}
The if let
statements in this example check if jsonResult can be cast to NSDictionary or NSArray and if they can set myDict
/ myArray
to a type cast version of jsonResult and enter the if body. If they can't be cast the code inside the if won't be executed. It's functionally the same as your solution, but a feels a bit more concise and cleaner to me.
Also, since you used the option NSJSONReadingOptions.MutableContainers
you may want to cast as NSMutableArray
and NSMutableDictionary
.
Upvotes: 1
Reputation: 349
Changing
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
to
if let jsonResult: AnyObject = NSJSONSerialization.JSONObjectWithData(data,options:nil,error: nil) {
if jsonResult is NSDictionary {
var myDict: NSDictionary = jsonResult as NSDictionary
println("myDict:\(myDict)")
}
else if jsonResult is NSArray {
var myArray: NSArray = jsonResult as NSArray
println("myArray:\(myArray)")
}
}
Got everything working. It was able to parse it as a NSArray and not a NSDictonary. As per code in a stack overflow chat, the code I have now will work for both JSON Arrays and JSON Objects that are returned by a Http request.
Upvotes: 4