I have issue that I can't retrieving json data in swift, I kept getting error message
var url = NSURL(string: getDataURL)!
var data = NSData(contentsOf: url as URL)
do {
jsonArray = try JSONSerialization.jsonObject(withData: data, options: .allowFragments)!
}
catch let error {
}
I was working with Objective C but I want to switch to Swift language
Folks, please use the code completion feature to find the proper syntax
When you type JSONSerialization. you will see
The appropriate method is
JSONSerialization.jsonObject(with:data, options: .allowFragments)
Or press ⇧⌘0 (zero not O) and look up the method in the documentation by typing or pasting the class. Every developer must be able to read the documentation.
Aside from that you have to cast the result of the deserialization to the expected type
jsonArray = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [[String:Any]]
Try this code send request and get data.
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(fooData!, options: []) as? NSDictionary
{
print(jsonResult)
}else{
return failure(NSError)
}
Related
I am new to the world of JSON. I just got started with JSON in Swift.
Right now, I have the following function:
func forShow() {
// Using ACORN API to fetch the course codes
guard let url[enter image description here][1]Online = URL(string: "https://timetable.iit.artsci.utoronto.ca/api/20179/courses?code=CSC") else { return }
let session = URLSession.shared
session.dataTask(with: urlOnline) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
print(data)
do {
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
print(json)
} catch {
print(error)
}
}
}.resume()
}
I get a response with all courses having 'CSC' in their code String. I want to form an array with all complete course codes based on the response. I will paste response for one course here:
So, I want to access all the course codes seen in the image. It's "CSC104H1-F-20179" I want to to be able to access.
Treat your JSON like a dictionary. You have all the course names at the top level, so fortunately you don't have to dig deep in the hierarchy.
So, where you have:
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
print(json)
Change to:
if let arrayOfCourses = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [[String: Any]] {
for (course, _) in arrayOfCourses {
print(course)
}
}
I am calling REST API to get a response from the server and also testing for bad data type to caught in try catch block nut app still crashes with below error:
Could not cast value of type '__NSArrayM' (0x10575ee00) to 'NSDictionary' (0x10575f2d8).
let dataTask = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error!)
return
}
do {
let responseObject = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as! Dictionary<String,String>
print(responseObject)
} catch let jsonError {
print(jsonError)
}
}
dataTask.resume()
For this, I also found the solution that I should check data with JSON format first then use JSONSerialization.
if JSONSerialization.isValidJSONObject(data){
responseObject = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as! Dictionary<String,String>
}
else {
print("Error")
}
I want to know that if type cast value error not caught by the try-catch block then what is a use of try-catch block in network call. I can simply check for the JSON format and the pass the response object.
What is a good programming practice?
NOTE : Error is not an issue I just don't want my should crash an app when data type changes form dictionary to array or other than specified type.
This is not about valid JSON, you are getting this crash because your JSON at root is Array not Dictionary and you are trying to cast the result of jsonObject(with:) to Dictionary that is the reason you are getting this crash also there is no need to specify mutableContainers with Swift.
do {
let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as! [[String:Any]]
print(responseObject)
} catch let jsonError {
print(jsonError)
}
Edit: If you don't know your JSON time then you can use if let like this way.
do {
let responseObject = try JSONSerialization.jsonObject(with: data, options: [])
if let responseArray = responseObject as? [[String:Any]] {
//Access array
}
else if let responseDictionary = responseObject as? [String:Any] {
//Access dictionary
}
print(responseObject)
} catch let jsonError {
print(jsonError)
}
I'm trying to integrate a login API in my iOS project. When i hit that API in browser it gives me correct JSON response. Whereas, when i call it in my app, i'm unable to read JSON. Code is as:
let url = NSURL(string: "myURL")
let request = NSURLRequest(URL: url!)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
if error != nil {
print (error)
}
do {
//jsonDict is always nil
if let jsonDict = try self.jsonFromData(data!) {
print (jsonDict)
}
}
catch {
print ("hi")
}
}
jsonFromData is as:
private func jsonFromData(jsonData: NSData) throws -> [NSDictionary]?
{
var jsonDict: [NSDictionary]? = nil
do
{
jsonDict = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.AllowFragments) as? [NSDictionary]
}
catch
{
throw(error)
}
return jsonDict
}
Response of API, when hit in browser is as:
Please help me, what i am doing wrong. Thanks.
UPDATE:
I just checked that if i convert data to String, it gives correct value. i.e.
let string = NSString(data: jsonData, encoding: NSASCIIStringEncoding)
print (string)
//OUTPUT: Optional({"Authenticated":true,"CustomerID":000,"CustomerName":"TEMP","Members":[{"MemberID":000,"MemberNumber":"000","MembershipID":00,"MembershipExpiration":"\/Date(1517464799000-0600)\/","ValidBuyerTypes":[0]}]})
Look at your code where you decode the JSON and the as? statement. You are trying to get an array of NSDictionary. Your JSON as printed contains a single dictionary, not an array.
This looks right to me. The only thing I can think is that (despite what the string output looks like) the top level container of your response is NOT an NSDictionary. In your jsonFromData function, instead of assuming the result of JSONObjecWithData will be an NSDictionary, I would say:
let iDunnoWhatThisIs = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.AllowFragments) // don't cast this to NSDictionary
and see what you get back. It should either be a dictionary or an array, however, since you have NSJSONReadingOptions.AllowFragments set for the options, it's possible that it could be something else entirely. Start with making SURE you're actually getting back what you're assuming you are and go from there.
Try using NSKeyedUnarchiver instead:
jsonDict = NSKeyedUnarchiver.unarchiveObjectWithData(jsonData)! as NSDictionary
I have the following code fetching json data via an API.
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
// print("Response: \(response)")
// print("DATA: \(data)")
if data != nil {
do {
print( NSString(data: data!, encoding: NSUTF8StringEncoding))
if let jsonResults = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSArray {
print("\n\nThe return JSON looks like this: \(jsonResults)\n\n")
}
} catch {
print("\n\nProblem getting JSON back from GET API.\n\n")
}
} else {
print("API Not Available") // data was nil
}
}) // task
task.resume()
The "print" of the NSString shows what to my eyes looks like valid JSON. The console shows this as:
Optional({"id":15,"user_id":11,"breed_id":593,"gender":"Male","age_years":5,"tally":{"count":1246,"struvite":716,"calcium_oxalate":388,"urate":217,"calcium_phosphate":30,"silica":21,"compound":41},"created_at":"2016-02-04T08:26:14.719-06:00","updated_at":"2016-02-04T08:26:14.719-06:00"})
However, the "if let jsonResults =" statement does execute successfully (there is no jsonResults printed) and the catch does not execute either -- so it seems like a silent error.
A very similar call works on another part of the API. The only big difference is that "tally" in the JSON return on this call is nested.
Any suggestions are appreciated.
The JSON may not be serialised properly, so try to replace:
if let jsonResults = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSArray
with:
if let jsonResults = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! [String: AnyObject]
let jsonResults = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSMutableDictionary
This implementation is a lot neater, and you don't have to specify their data types.
The answer was a combination of dzk and ishaq's responses.
I replaced
if let jsonResults = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSArray
with:
if let jsonResults = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
The essential piece was casting it as a Dictionary, not an Array.
I am using REST to get JSON data and then parse it. To do this I am using NSJSONObjectWithData, as far as I'm aware this method used to have an error handler within its parameters but it's no longer there. In my code here:
let err: NSError?
let options:NSJSONReadingOptions = NSJSONReadingOptions.MutableContainers
var jsonResult = NSJSONSerialization.JSONObjectWithData(data!, options: options) as! NSDictionary;
I get an error which says:
"Call can throw, but it is not marked with 'try' and the error is not handled"
How would I go about fixing this error?
Here is the correct implementation,
do {
let jsonDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
//Use your dictionary here.
print("JSON : \(jsonDictionary)")
}
catch {
print(error)
//Handle any error.
}