Nested JSON data will cause crash using NS Dictionary (in Swift) - ios

I'm trying to fetch movie information in JSON format using JSONSerialization in Swift and save it as an NSDictionary. However, calling the Rotten Tomatoes API (in which information is nested) will cause my Playground to crash (without giving me any useful errors).
I know the code is somewhat valid, since calling other APIs which don't nest their data works (but don't fulfill my need).
Here's the code:
func getJSON(urlToRequest: String) -> NSDictionary {
var url = NSURL(string: urlToRequest)
var error: NSError?
let jsonData: NSData = NSData.dataWithContentsOfURL(url , options: NSDataReadingOptions.DataReadingMapped, error: nil)
let jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
return jsonDict
}
let movieData: NSDictionary = getJSON(apiURL)
here's a sample from the Rotten Tomatoes API JSON (shortened for illustration purposes, this is the actual JSON file, not the output from my code)
{
"id": 770672122,
"title": "Toy Story 3",
"year": 2010,
"genres": ["Animation", "Kids & Family", "Science Fiction & Fantasy", "Comedy"],
"release_dates": {
"theater": "2010-06-18",
"dvd": "2010-11-02"
},
"ratings": {
"critics_rating": "Certified Fresh",
"critics_score": 99,
"audience_rating": "Upright",
"audience_score": 89
}
}

This code works for me in a Swift iOS app (crashes Xcode when run in a playground:
func getJSON(urlToRequest: String) -> NSDictionary {
var url = NSURL(string: urlToRequest)
var error: NSError?
let jsonData: NSData = NSData.dataWithContentsOfURL(url , options: NSDataReadingOptions.DataReadingMapped, error: nil)
let jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
return jsonDict
}
let apiURL = "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122.json?apikey=9p4xwzpgt8xp2vahnyx2sc6g"
let movieData: NSDictionary = getJSON(apiURL)
println(movieData)
It looks like the crash you are getting is a playground error.
Note, Swift is basically guaranteed to have bugs, it is an early Beta.
Also explicitly state they the JSON is example code, not fro running your code.

Related

Access data from NSDictionary

I'm trying to get data from an NSDictionary in Swift but I'm not able to do this.
Here is the code
let urlPath = "http://ws-report.goocity.it/Stats/json/GetReport"
let url: NSURL = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
var result: NSDictionary
if error != nil {
// If there is an error in the web request, print it to the console
println(error.localizedDescription)
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if err != nil {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
}
else{
//var arr : NSArray = jsonResult.valueForKey("Stats") as NSArray
//var cash: String? = jsonResult.valueForKey("Cash") as? NSString
let stats = jsonResult["Stats"]! as [[String : AnyObject]]
}
})
task.resume()
You can see the JSON clicking on the urlPath.
I still receive the following error on the let stats = ...
Thread 5: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
I've just checked out few other posts here on stackoverflow and anywhere, but no answer is good for my issue.
I need to get all JSON field values in many variables (like cash, lastUpdate, totalPartners, etc).
Your json is not an array of Dictionaries, it is just a Dictionary.
Change [[String: AnyObject]] to [String: AnyObject] and it will work.

Parse Google Calendar JSON in SWIFT

I'm brand new to Swift development. I'm trying to build a basic app which will read a feed from Google Calendar which is returned in JSON.
I am able to use a NSURLConnection.sendAsynchronousRequest call as described in this thread: Make REST API call in Swift and I get a result of some sorts.
My problem is I am unable to parse the JSON into some meaningful objects from which I can create a list of upcoming events.
My code this far is:
var url : String = "some url"
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
if (jsonResult != nil){
// No idea how to parse this object as it seems to be a NSDictionary but battling to interact with it.
}
else
{
}
})
Any help would be greatly appreciated.
If you put a breakpoint after
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
then you'll be able to see the dictionary key/value pairs. I copied/pasted your code and see this:
You can access the values by using jsonResult.objectForKey("keyName"). I'm also going to downcast using as DataType.
Example)
let encoding = jsonResult.objectForKey("encoding") as String
let version = jsonResult.objectForKey("version") as String
let feed = jsonResult.objectForKey("feed") as NSDictionary

Unable to get the value of JSON - Swift

I tried to get the value of "seed" from json response. But i am getting nil.
Json Response:
{
"response": {
"params": {
"rows": "20",
"defType": "abc",
"seed": "381786611"
}
}
}
Swift Parsing:
if let responseHeader:AnyObject = object?["response"] as? NSDictionary {
if let t = (responseHeader["params"] as? NSDictionary){
let t1 = t["seed"] as? String
println("result is \(t1)") // This returns nil
}
}
Json Parsing
func processJsonToDictionary(object:AnyObject?) -> AnyObject?{
if object != nil {
if let data: AnyObject = object {
var parseError: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(object as NSData!, options: NSJSONReadingOptions.MutableContainers, error: &parseError) as? NSDictionary
if(parseError != nil){
return parseError
}
else{
return jsonResult
}
}
}
return nil
}
I am not able to get the value of t1. it always returns nil.
How can i get the value.
Also, I put a breakpoint and tried to print the value of t1. But the Xcode Keeps crashing. Why?
I think the major problem here is only accessing a JSON object in swift.
var error: NSError?
let jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as NSDictionary
let resp = jsonDict["response"] as? NSDictionary
let params = resp?["params"]?["seed"]
let seed = params!! as NSString
This is just to show you how a JSON object is accessed in swift. You can ofcourse change it according to your needs to remove unwanted Optional Chaining.
For easy JSON manipulation in Swift you could try this little library. It seems pretty easy and you could do this:
var dictionary: [String: AnyObject]!
if let json = NKJSON.parse(yourNSDataObject) {
dictionary <> json[NKJSON.rootKey]
}
First confirm that the response which you are getting is in json format or in string format.
For json parsing you can use swifty json pod

NSJSONSerialization no returns error

There code:
var err: NSError
var jsonDict = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as Array<NSDictionary>
If data has JSON it's works perfect. But if there something other (not JSON Array) it's just has fatal error and iOS simulator close with EXC_BAD_INSTRUCTION.
So there no call err. How I can check data before? Or catch the error.
(Sorry, am in a hurry, no description yet.)
var err: NSError?
var jsonDict: AnyObject!
var data: AnyObject = "{ }".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
if let d = data as? NSData {
jsonDict = NSJSONSerialization.JSONObjectWithData(d, options: NSJSONReadingOptions.MutableContainers, error: &err)
if let dict = jsonDict as? NSDictionary {
// Do something with `dict`
println(dict)
}
}
This probably happens because JSONObjectWithData is declared to return id, but in reality it returns NSDictionary*, NSArray* or nil - in Swift, assigning nil to a variable of type id crashes by design. You need to give jsonDict a type, probably an optional NSMutableDictionary* or NSMutableArray*.

JSON Serialization in Swift iOS

How can I serialize JSON in swift? I am trying to serialize using this method, however it is causing EXC_BAD_INSTRUCTION. For downloading JSON data, I am using NSURLConnection.
var sJson : NSDictionary = NSJSONSerialization.JSONObjectWithData(nsMutData, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
How can I solve it?
Regards
Your root-level data is an array of dictionaries -- not a dictionary; therefore replace your line with:
var sJson = NSJSONSerialization.JSONObjectWithData(nsMutData, options: .MutableContainers, error: nil) as NSArray
I tested it and it now works with your data.
Here's how I tested it after having created a "json.txt" file in my project:
var filePath = NSBundle.mainBundle().pathForResource("json", ofType:"txt")
var nsMutData = NSData(contentsOfFile:filePath)
var sJson = NSJSONSerialization.JSONObjectWithData(nsMutData, options: .MutableContainers, error: nil) as NSArray
This is the swift 2.0 way
let path : String = NSBundle.mainBundle().pathForResource("jsonDict", ofType: "JSON")!;
let data : NSData = NSData(contentsOfFile: path)!;
var jsonDictionary : NSDictionary
do {
jsonDictionary = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as! NSDictionary
} catch {
print(error)
}
In Swift 4+, JSON Serialization is best done by utilizing the Decodable and Encodable protocols.
Apple docs about encoding/decoding (or serializing/deserializing)
custom types
Download sample code from Apple on this page
There is also a detailed tutorial by Ray Wenderlich: Encoding and Decoding in Swift

Resources