Swift 2.0 How to parse JSON? - json

I am coding a hangman game and am loading the possible words into my app using json text files. I tried to follow the examples of others on this website but I am getting errors from Xcode.
I tried the following code based on another answer:
import Foundation
var error: NSError?
let jsonData: NSData = /* get your json data */
let jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as NSDictionary
But I got an errors on line 4 with jsonDict that said "call can throw but is not marked with try, and the error is not handled" and "Type JSONReadingOptions does not conform to protocol NilLiteralConvertible".
Here is the JSON File I would like to parse:
{
“wordList” : {
“difficulty” : “Easy”
“list” : [
“fireplace”,
“apple”,
“january”,
“tooth”,
“cookies”,
“mysterious”,
“essential”,
“magenta",
“darling”,
“pterodactyl”
]}}
I would like to be able to go into my list array and get values. Thank you very much for any help!

In Swift 2 you need to use the new error handling API instead of passing a reference to an NSError:
do {
let jsonDict = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions(rawValue: 0)) as? NSDictionary
if let jsonDict = jsonDict {
// work with dictionary here
} else {
// more error handling
}
} catch let error as NSError {
// error handling
}
You also can't pass nil as value to the options parameter, you need to pass a value of type NSJSONReadingOptions.
That said, the most common approach for parsing JSON in Swift is currently using third party libraries, such as Argo because they can save you a lot of code that is necessary to validate and safely cast the content of your JSON data to the correct Swift types.

Related

Swift Escaping Unwanted Backslash Characters on JSON Encoding

I’m getting a bunch of unneeded “escaped back-slash” characters when I convert my Swift Dictionary object using JSONSerialization. It’s only happening on one of my Key-Value pairs - the one that has a URL in it:
"image" : "http:\/\/www.someWebSite.com\/images/\triangleImage.jpg”
I tried to run JSONSerialization twice thinking it might solve the problem - but it just crashes. Swift is not my main language so I’m not really sure how to fix this?
Here’s my code:
// Creating the Dictionary:
triangleDictionary["name"] = "triangle 01”
triangleDictionary["image"] = "http://www.someWebSite.com/triangleImage.jpg"
triangleDictionary["description"] = "a geometric shape"
// Serializing it to a JSON object:
do {
let triangleData = try JSONSerialization.data(withJSONObject: triangleDictionary, options: [.prettyPrinted])
let triangleDataJSONString = String(data: triangleData, encoding: .utf8)!
print("triangleDataJSONString = \(String(describing: triangleDataJSONString))")
}
catch {
print("ERROR Serializing triangleData!: \(error)")
}
The output I get is almost perfect - except for those extra back-slashes:
{
"name" : “triangle 01”,
"description" : “a geometric shape”,
"image" : "http:\/\/www.someWebSite.com\/images/\triangleImage.jpg”
}
What do I need to do to fix this?
Add this line in your code
header('Content-Type: application/json');

Serializing data into JSON using older swift method 'JSONObjectWithData?

I'm sorry if this may seem that I haven't read or updated my information on Swift 2.2 but I actually already have and I've gone through the updated method but still am receiving errors(I didn't state them here because thats not my issue; my issue is writing the JSONObjectWithData in its updated syntax form)
I took this function from an older swift book and am trying to get it to Parse the data into JSON. I used the updated syntax for the method JSONObjectWithData() but wasn't able to piece the syntax pieces together. My problem isn't the compiler screaming at me with errors because I know that I was rewriting the JSONObjectWithData method wrong, heres the old syntax that I tried to rewrite but couldn't do so successfully.
I still haven't wrapped my head around the concept of parsing data into JSON even after studying the chapter and reading the Apple documentation, let alone try to rewrite the JSONObjectWithData method correctly. I searched a similar answer to this and could not figure out how to write this book method correctly in the updated syntax and have it run without errors. I've been stuck on this for 2 days.
func parseJson(data: NSData) {
var error: NSError?
let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: .allZeros, error: &error)
if error == nil {
if let unwrappedJson: AnyObject = json {
parseSongs(json: unwrappedJson)
}
}
}
Have you tried this block of code:
let json: AnyObject? = try! NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)

parsing Json Array swift 2 error

this code was function correctly but when i tried on swift 2, i start having this errors, does anyone know how to fix them? i already add the NSAppTransportSecurity to info list.
The app may be able to download a json array with images from server, but i'm not really sure how to do it on swift 2
I tried a lot of tutorials about swift 2 but didn't work
Try this....Use do catch instead of if let
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(dataObject, options:.MutableContainers) as? NSArray
self.images = jsonResult
} catch let error as NSError {
print(error)
}

Int does not conform to protocol 'StringLiteralConvertible'

Im trying to parse json in weather app, but have hit a snag that i cannot get past.
I do get an error, "Type 'int' does not conform to Protocol 'StringLiteralConvertible'" in the following code.
Ive tried casting the jsonResult["main"] but that does instead give the error "Operand of postfix should have optional type, type is AnyObject". Do i need to downcast the Array in some way and how, if so, should i do that?
I´ve searched so much for this but could not find any help in other posts. Code as follows.
func updateWeatherInfo(latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
Alamofire.request(.GET, AlongRequest)
.responseJSON { (_, _, JSON, error) in
println(JSON)
self.updateUISuccess(JSON as NSArray!)
}
}
func updateUISuccess(jsonResult: NSArray) {
self.loading.text = nil
self.loadingIndicator.hidden = true
self.loadingIndicator.stopAnimating()
if let tempResult = ((jsonResult["main"] as NSArray)["temp"] as? Double)
This would be easier to give a definitive answer to if you provide the JSON that you're trying to parse, but the error message you're getting is clear.
That error is because you're trying to access what you've declared as an NSArray instance with a string subscript, twice in this one line:
if let tempResult = ((jsonResult["main"] as NSArray)["temp"] as? Double)
jsonResult is declared as an NSArray parameter, and then you're casting jsonResult["main"] to NSArray before trying to subscript it with ["temp"]. The problem here is that NSArray (and built-in Swift arrays) only use integer-based subscripting. The error is saying that where the Swift compiler is expecting an Int, you've provided a string literal.
To fix this, you'll need to go in one of two directions. If the structure you're trying to access actually has these string keys, then you should be using NSDictionary instead of NSArray in both cases. If not, and it's an integer-index array, you should be using integers.

How do I access the data when I am using NSURLSession?

I am new to iOS development. I am using Swift and I have very little experience with Objective-C, so some of the other possibly related answers are tricky to understand. I am trying to understand how to use NSURLSession to get some data from a JSON file on the Web. I found some useful information about getting a file from a URL, but like this other StackOverflow user (NSURLSessionDataTask dataTaskWithURL completion handler not getting called), I heard that NSURLConnection was not the current way to get data, so I'm trying to use NSURLSession.
When I am getting my JSON from the bundle, I am using this extension to
Dictionary (I am pretty sure I got this code from a tutorial):
static func loadJSONFromBundle(filename: String) -> Dictionary<String, AnyObject>? {
let path = NSBundle.mainBundle().pathForResource(filename, ofType: ".json")
if !path {
println("Could not find level file: \(filename)")
return nil
}
var error: NSError?
let data: NSData? = NSData(contentsOfFile: path, options: NSDataReadingOptions(),
error: &error)
if !data {
println("Could not load level file: \(filename), error: \(error!)")
return nil
}
let dictionary: AnyObject! = NSJSONSerialization.JSONObjectWithData(data,
options: NSJSONReadingOptions(), error: &error)
if !dictionary {
println("Level file '\(filename)' is not valid JSON: \(error!)")
return nil
}
return dictionary as? Dictionary<String, AnyObject>
}
I'd like to do something similar for getting a dictionary from a JSON file that is on the web because I don't anticipate wanting to include all of my JSON files in the bundle. So far, I have this:
static func loadJSONFromWeb(urlstring: String) -> Dictionary<String, AnyObject>? {
let url = NSURL(string: urlstring)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config, delegate: nil, delegateQueue: NSOperationQueue())
var error: NSError?
//I think I am using the completionHandler incorrectly. I'd like to access the data from the download
let task = session.downloadTaskWithRequest(NSURLRequest(URL: url), {(url, response, error) in println("The response is: \(response)")
})
task.resume()
//Isn't this contentsOfURL thing supposed to go with the connection stuff rather than the session stuff?
//How can I do this with a session? How can I create and use a completionHandler? This way seems clunky.
let data: NSData? = NSData(contentsOfURL: url)
if !data {
println("Could not load data from file: \(url), error: \(error!)")
return nil
}
println("The data is: \(data)")
let dictionary: AnyObject! = NSJSONSerialization.JSONObjectWithData(data,
options: NSJSONReadingOptions(), error: &error)
if !dictionary {
println("The file at '\(url)' is not valid JSON, error: \(error!)")
return nil
}
return dictionary as? Dictionary<String, AnyObject>
}
I think that my actual question that most needs answering is this: Where
is the data? I don't think I am using sessions and tasks correctly. I feel like I'm
starting a session to connect to a specific URL and using resume() to
start the download task I want to make happen, but I don't know how to
get the data from that JSON file.
If I need to use a completionHandler and a request in a way similar to what I found here:
(popViewControllerAnimated work slow inside NSURLSessionDataTask) can someone please explain how the 'data' in the completionHandler relates to the data in the fie I am trying to read/download? I am a bit baffled by the completionHandler and how to use it properly.
I looked at the documentation for NSData as well, but I didn't see anything that helped me understand how to get data from my session (or how to initialize an instance of NSData given my session). As far as I can tell form the documentation for NSURLDownloadTask, the task itself is not how I can access the data. It looks like the data comes from the session and task through the completionHandler.
EDIT:
I also looked at the documentation for NSURLSessionDownloadDelegate, but I could really use an example in Swift with some explanation about how to use the delegate. This led me to the URL Loading System Programming Guide. I'm guessing the benefits of using a session must be huge if the documentation is this complicated. I'm going to keep looking for more information on the URL Loading System.
I found this answer helpful (but I'm so new I can't upvote anything yet): https://stackoverflow.com/a/22177659/3842582 It helped me see that I am probably going to need to learn to use a delegate.
I also looked at the URL Loading System Programming Guide. I think what I really need is help with a completionHandler. How can I get my data? Or, am I already doing it correctly using NSData(contentsOfURL: url) (because I don't think I am).
Thank you in advance for any help you can offer!
First, let data: NSData? = NSData(contentsOfURL: url) will return your JSON synchronously. Did you try that and get this working simply? That way you can get started with the rest of your processing while figuring out NSURLSession.
If you're going to use NSURLSession, or a lot of other things in iOS, you need to learn delegates. Fortunately, they're easy. In terms of syntax you just add it to your class declaration like you were inheriting from it. What that does is say that you are going to implement at least the required functions for the delegate. These are callback functions which are generally pretty well documented. It is quite straightforward once you understand it.
If this is not a "heavyweight" project that really needs NSURLSession, you should look at this Swift library. Besides being a really nice way to deal with JSON there is a synchronous call to directly load the JSON from a url. https://github.com/dankogai/swift-json/
Why is NSURLConnection not the correct way to get data? You just should be careful with synchronous requests. Here is an example of how to get data from an url.
func synchronousExampleRequest() -> NSDictionary {
//creating the request
let url: NSURL! = NSURL(string: "http://exampledomain/apiexample.json")
var request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
var error: NSError?
var response: NSURLResponse?
let data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
error = nil
let resultDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers, error: &error) as! NSDictionary
return resultDictionary
}