Serializing data into JSON using older swift method 'JSONObjectWithData? - json

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)

Related

how to get values of JSON using swiftyjson

I have this JSON
{
"chatUsers":"[
{"id":"5","sender_id":"6","receiver_id":"1","content":"hi","datetime":"2016-11-19 00:00:00"},
{"id":"4","sender_id":"1","receiver_id":"2","content":"hello","datetime":"2016-11-11 00:00:00"},
{"id":"2","sender_id":"1","receiver_id":"3","content":"how are you","datetime":"2016-11-04 00:00:00"}
]",
"chatsCount":3
}
now I have this code to get data from the url :
let StringUrl = NSURL(string: url) as NSURL!
let Data = NSData(contentsOfURL: StringUrl) as NSData!
let ReadableData = JSON(data: Data)
let result = ReadableData["chatUsers"][0]["id"].string! as String // this should gives 5
but it always gives this error :
fatal error: unexpectedly found nil while unwrapping an Optional value
any idea why ?
There's quite a bit wrong with the example you provided above, but for the sake of getting you moving in the right direction, let me give you a some advice and a quick solution to your issue.
First off, don't start your variables with an uppercase character. Its not a set in stone rule or anything, but it's better practice to use camelCase as it will make your code more readable and avoid confusion.
Secondly, you are doing lots of force casting and force unwrapping of optional values which will make your application prone to crashes due to the same error you are getting now. I would take a look at the following for some better guidance: https://stackoverflow.com/a/25195633/4660602
Third, when posting on SO, please make sure you clearly give your question context as some users may believe you are asking a question about what optionals are and why you are getting the fatal error: unexpectedly found nil while unwrapping an Optional value error.
With that said, in the future please make sure to take a look at the SwiftyJSON docs as they pretty clearly demonstrate how to use the library. The reason your code is not working is because you are handling the JSON incorrectly. Here is an updated example:
let StringUrl = NSURL(string: url) as NSURL!
let Data = NSData(contentsOfURL: StringUrl) as NSData!
let ReadableData = JSON(data: Data)
let chatUsers = ReadableData["chatUsers"].arrayValue
let result = chatUsers[0]["id"].stringValue
or if you need to iterate through all the users:
let StringUrl = NSURL(string: url) as NSURL!
let Data = NSData(contentsOfURL: StringUrl) as NSData!
let ReadableData = JSON(data: Data)
for chatUser in ReadableData["chatUsers"]{
print(chatUser.1["id"].stringValue)
}
Please note I did not update your variable identifiers to the correct convention for the sake of not confusing you, but you should really follow the correct convention as I mentioned in my first point.
Good luck.
EDIT: Forgot to mention that your JSON is incorrectly formatted. Please fix your JSON data to the correct JSON format so that SwiftyJSON can correctly interpret it. You are receiving index out of range because SwiftyJSON does NOT know chatUsers is an array because the square brackets are wrapped in double quotes when they should not be. So
"chatUsers":"[
{"id":"5","sender_id":"6","receiver_id":"1","content":"hi","datetime":"2016-11-19 00:00:00"},
{"id":"4","sender_id":"1","receiver_id":"2","content":"hello","datetime":"2016-11-11 00:00:00"},
{"id":"2","sender_id":"1","receiver_id":"3","content":"how are you","datetime":"2016-11-04 00:00:00"}
]"
should be
"chatUsers": [
{"id":"5","sender_id":"6","receiver_id":"1","content":"hi","datetime":"2016-11-19 00:00:00"},
{"id":"4","sender_id":"1","receiver_id":"2","content":"hello","datetime":"2016-11-11 00:00:00"},
{"id":"2","sender_id":"1","receiver_id":"3","content":"how are you","datetime":"2016-11-04 00:00:00"}
]

Extra argument 'error' in call? But I don't have an 'error' variable at all?

I don't have an error variable anywhere, is this a bug in Xcode? I'm very confused on what could be wrong. I've searched all of stack overflow for an answer on this, found nothing. I've tried for several hours to figure out why I'm getting this error for the line of func parseJson( data: NSData){
I'm a beginner who studies Swift day and night.
Here is my code below:
func parseJson( data: NSData){
do{
let json: AnyObject = try NSJSONSerialization.JSONObjectWithData(data, options: [])
if let unwrappedJson: AnyObject = json{
parseSongs(unwrappedJson)
}
}catch{
}
}
Clean the project and build
If that doesn't word
Restart xcode
Rewrite the code

Swift 2.0 How to parse 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.

Swift json parsing error: Could not cast value of type NSCFConstantString to NSArray

I have some problems with parsing json using swift code.
json example
{"responce": "ok","orders": [{"id":"1"), {"id":"2"}, {"id":"3"} ]}
and this code working fine
let dataArray: NSArray = jsonResult["orders"] as! NSArray
but if I get {"responce": "ok","orders": ""} I got the error: Could not cast value of type __NSCFConstantString (0x10c7bfc78) to NSArray (0x10c7c0470).
Can I somehow check if value is array or not to do not crashed?
Yes you can check if the value is a NSArray by doing this:
if let dataArray = jsonResult["orders"] as? NSArray {
}
If the result of jsonResult["orders"] is a NSArray then dataArray will be set and you will go into the if statement.
This error is most likely caused by the response you are getting back from what I assume is a server not being JSON, but being something like an HTML/XML response saying that the server either could not be reached, or that your query/post request was invalid (hence the fact that the value was an "NSCFConstantString").
Using James' answer is a perfectly good way to check that the value is an Array, but you might want to test your requests using a program like Postman to see what he response is, and then hard code a way to handle that error on the user side.

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
}