Swift Errors Thrown from here are not handled - json

I have had my code working in Xcode 6 but since I got Xcode 7 I cannot figure out how to fix this. The let jsonresult line has an error that says Error thrown from here are not handled. Code is below:
func connectionDidFinishLoading(connection: NSURLConnection!) {
let jsonresult:NSDictionary = try NSJSONSerialization.JSONObjectWithData(self.bytes, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
print(jsonresult)
let number:Int = jsonresult["count"] as! Int
print(number)
numberElements = number
let results: NSDictionary = jsonresult["results"] as! NSDictionary
let collection1: NSArray = results["collection1"] as! NSArray
Thanks

If you look at the definition of JSONObjectWithData method in swift 2 it throws error.
class func JSONObjectWithData(data: NSData, options opt: NSJSONReadingOptions) throws -> AnyObject
In swift 2 if some function throws an error you have to handle it with do-try-catch block
Here is how it works
func connectionDidFinishLoading(connection: NSURLConnection!) {
do {
let jsonresult:NSDictionary = try NSJSONSerialization.JSONObjectWithData(self.bytes, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
print(jsonresult)
let number:Int = jsonresult["count"] as! Int
print(number)
numberElements = number
let results: NSDictionary = jsonresult["results"] as! NSDictionary
let collection1: NSArray = results["collection1"] as! NSArray
} catch {
// handle error
}
}
Or if you don't want handle error you can force it with try! keyword.
let jsonresult:NSDictionary = try! NSJSONSerialization.JSONObjectWithData(self.bytes, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
print(jsonresult)
As with other keywords that ends ! this is a risky operation. If there is an error your program will crash.

Related

Cast from '(key: Any, value: Any)' to unrelated type '[String : Any]' always fails

I am working on a project and have reached a stage where I want to display data from a web service in a table view. My json data is in dictionary format and I am taking loop for fetching the data from dictionary by using key but it's getting the warning. So, please help me for this type of warning.
My loop is:-
let fetchedData = try JSONSerialization.jsonObject(with: data!, options: []) as! NSDictionary
for eachFetchedRestaurant in fetchedData {
let eachRestaurant = eachFetchedRestaurant as! [String : Any]
let restaurantName = eachRestaurant["restName"] as! String
let restaurantImage = eachRestaurant["restaurant_image"] as! String
self.fetchedRestaurant.append(Restaurants(restaurantName: restaurantName, restaurantImage: restaurantImage))
}
print(self.fetchedRestaurant)
Getting warning on this line:-
let eachRestaurant = eachFetchedRestaurant as! [String : Any]
Cast from '(key: Any, value: Any)' to unrelated type '[String : Any]' always fails
Thanks in advance for helping!!!
Since JSON response is array of (key, value) format, so your fetch data should be of [[String:Any]] format. Here is the updated code.
let fetchedData = try JSONSerialization.jsonObject(with: data!, options: []) as! [[String:Any]]
for (key,eachFetchedRestaurant) in fetchedData {
let eachRestaurant = eachFetchedRestaurant as! [String : String]
let restaurantName = eachRestaurant["restName"] as! String
let restaurantImage = eachRestaurant["restaurant_image"] as! String
self.fetchedRestaurant.append(Restaurants(restaurantName: restaurantName, restaurantImage: restaurantImage))
}
print(self.fetchedRestaurant)
First of all don't use NSDictionary and NSArray in Swift, use native types.
You are applying array related enumeration API to a dictionary. The dictionary related API is
for (key, eachFetchedRestaurant) in fetchedData
You've got two options:
fetchedData is indeed expected to be dictionary then cast
let fetchedData = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
and use the mentioned enumeration API
(the more likely one) fetchedData is expected to be an array then you have to cast
let fetchedData = try JSONSerialization.jsonObject(with: data!) as! [[String:Any]]

Swift JSONSerialization.jsonObject Error

I've looked around but I don't find an answer to fix this error that has been bugging me. I tried adding a "as! NSMutableArray" but that gave me another error. Any ideas on how to fix it? I converted my project from Objective-C to Swift, so hopefully the code is all good I had 20+ errors now I'm down to 3 errors. Thank you.
Error Message:
'jsonObject' produces 'Any', not the expected contextual result type 'NSMutableArray'
Code for retrieving data from server
// Retrieving Data from Server
func retrieveData() {
let getDataURL = "http://ip/example.org/json.php"
let url: NSURL = NSURL(string: getDataURL)!
do {
let data: NSData = try NSData(contentsOf: url as URL)
jsonArray = JSONSerialization.jsonObject(with: data, options: nil)
}
catch {
print("Error: (data: contentsOf: url)")
}
// Setting up dataArray
var dataArray: NSMutableArray = []
// Looping through jsonArray
for i in 0..<jsonArray.count {
// Create Data Object
let dID: String = (jsonArray[i] as AnyObject).object(forKey: "id") as! String
let dName: String = (jsonArray[i] as AnyObject).object(forKey: "dataName") as! String
let dStatus1: String = (jsonArray[i] as AnyObject).object(forKey: "dataStatus1") as! String
let dStatus2: String = (jsonArray[i] as AnyObject).object(forKey: "dataStatus2") as! String
let dURL: String = (jsonArray[i] as AnyObject).object(forKey: "dataURL") as! String
// Add Data Objects to Data Array
dataArray.add(Data(dataName: dName, andDataStatus1: dStatus1, andDataStatus2: dStatus2, andDataURL: dURL, andDataID: dID))
}
self.myTableView.reloadData()
}
The jsonObject function will return a value of type Any but the jsonArray's type of NSMutableArray. And this function will throw an error if something is wrong, put a try keyword before it. In my experience, let change the type of jsonArray to array of dictionary, so you will extract data with ease.
do {
let data: Data = try Data(contentsOf: url as URL)
let jsonArray: [[String: AnyObject]] = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [[String: AnyObject]]
print("json: \(jsonArray)")
for dict in jsonArray {
let dataName = dict["dataName"] as! String
print("dataName: \(dataName)")
}
}
catch {
print("Error: (data: contentsOf: url)")
}

Strange behaviour of optionals in Swift 3

I have experienced a strange behaviour when parsing JSON data using Swift 3.
do {
let json = try JSONSerialization.jsonObject(with: data!, options: []) as! NSDictionary
let items:[AnyObject] = (json["items"] as? [AnyObject])!
for item in items {
let id:String = item["id"] as! String
print("ID: \(id)")
let info = item["volumeInfo"] as AnyObject
print(info)
let title = info["title"]
print(title)
}
} catch {
print("error thrown")
}
This produces the following output. Notice that info is an optional but if I try to unwrap it it states it is not an optional! The script crashes on let title = info["title"] As a result I can't access the title key. This behaviour has changed since Swift 2.
ID: lbvUD6LUyV8C
Optional({
publishedDate = 2002;
publisher = "Sams Publishing";
title = "Java Deployment with JNLP and WebStart";
})
You can do something like:
do {
let json = try JSONSerialization.jsonObject(with: data!) as! [String: Any]
let items = json["items"] as! [[String: Any]]
for item in items {
let id = item["id"] as! String
let info = item["volumeInfo"] as! [String: Any]
let title = info["title"] as! String
print(id)
print(info)
print(title)
}
} catch {
print("error thrown: \(error)")
}
I might suggest excising the code of the ! forced unwrapping (if the JSON was not in the form you expected, do you really want this to crash?), but hopefully this illustrates the basic idea.
The runtime type of info is Optional<Something>, but the compile time type (as you explicitly cast it) is AnyObject. How is the compiler supposed to know that the AnyObject will happen to be an Optional<Something> unless you tell it (in the form of a cast)?
Try:
let info = item["volumeInfo"] as AnyObject?
Now the compiler knows it's an Optional<AnyObject>, so you can unwrap it.
In Swift 3 the compiler must know the types of all subscripted objects if it's an array or dictionary. AnyObject – which has been changed to Any in Swift 3 – is not sufficient.
Since you know that the value for key volumeInfo is a dictionary cast it accordingly preferably using optional bindings
let info = item["volumeInfo"] as? [String:Any] {
print(info)
let title = info["title"] as! String
print(title)
}
This should do:
guard let json = try? JSONSerialization.jsonObject(with: data!, options: []) as! [String: AnyObject],
let items = json["items"] as! Array<AnyObject>? else {
return
}
for item in items {
let id = item["id"] as! String
if let info = item["volumeInfo"] as? [String: AnyObject] {
let title = info["title"] as! String
} else {
// do something
}
}

How to cast a subscript member to NSArray Swift 3

Returns an error message: Type β€˜Any’ has no subscript members in last 2 lines of code. I can^t solve this for NSArray in Swift 3: Any thoughts?
let weatherDictionary: NSDictionary = (try! JSONSerialization.jsonObject(with: dataObject!, options: [])) as! NSDictionary
_ = try JSONSerialization.jsonObject(with: dataObject!, options: .allowFragments) as! [String:Any]
then
struct Weekly{
var dayZeroTemperatureMax: Int
var dayZeroTemperatureMin: Int
init (weatherDictionary: NSDictionary) {
let weeklyWeather = weatherDictionary["daily"] as! NSDictionary
let weeklyForcast = weeklyWeather["data"] as! NSArray
//DAY ZERO
dayZeroTemperatureMax = weeklyForcast[0]["temperatureMax"] as! Int
dayZeroTemperatureMin = weeklyForcast[0]["temperatureMin"] as! Int
}
}
Try changing your code to this :
let weeklyWeather = weatherDictionary["daily"] as! [String: AnyObject]
let weeklyForcast = weeklyWeather["data"] as! [[String: Any]]
in this same project you might need to change this too (in WeatherAlerts) :
init (weatherDictionary: [String: Any]) {
if let weatheralerts = (weatherDictionary["alerts"] as? [[String: Any]]) {
userAlert = weatheralerts[0]["title"] as! String
} else {
userAlert = ""
}
}
I don't really know the reason to change this , if anyone have an explanation please comment here.
but in the same project I had a "fatal error: unexpectedly found nil while unwrapping an Optional value" error here , do you have any idea? what change about URLSessionDownloadTask ?

Get JSON in Swift

This is my code to get JSON, and it's work with this url I found on an other questions : http://binaenaleyh.net/dusor/.
But, when I use it with this url : http://www.netcampus.fr/api/schools, it didn't work at all. I have an error who said : "exc_breakpoint (code=exc_i386_bpt subcode=0x0)"
Is my code wrong, or is it the JSON data ?
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var myData:NSData = getJSON("http://www.netcampus.fr/api/schools")
println(myData) // show me data
var myDict:NSDictionary = parseJSON(myData)
println(myDict)
}
func getJSON(urlToRequest: String) -> NSData{
return NSData(contentsOfURL: NSURL(string: urlToRequest))
}
func parseJSON(inputData: NSData) -> NSDictionary{
var error: NSError?
var boardsDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary // error here
return boardsDictionary
}
}
Your parseJSON method crashes when parsing the second JSON. NSJSONSerialization maps its contents to an array and you are expecting a dictionary:
var boardsDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary // error here
As #reecon pointed out ,your code should be like this
//JSON Parsing
func JSONParsingSample() {
var myData:NSData = getJSON("http://www.netcampus.fr/api/schools")
//println(myData) // show me data
var myDict:NSArray = parseJSON(myData)
println(myDict)
}
func getJSON(urlToRequest: String) -> NSData{
return NSData(contentsOfURL: NSURL(string: urlToRequest))
}
func parseJSON(inputData: NSData) -> NSArray{
var error: NSError?
var boardsDictionary: NSArray = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSArray
return boardsDictionary
}
//end
let urlString = "webAPI"
var request = URLRequest(url: URL(string: urlString)!)
let session = URLSession.shared
request.httpMethod = "GET"
session.dataTask(with: request)
{
data, response, error in
if error != nil
{
print(error!.localizedDescription)
return
}
do
{
let jsonResult: NSDictionary? = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
self.dict = jsonResult as! NSMutableDictionary
print("Synchronous\(jsonResult)")
DispatchQueue.main.async
{
let url = URL(string: ((((self.dict.value(forKey: "sources") as! NSArray).object(at: 5) as! NSDictionary).value(forKey: "urlsToLogos") as? NSDictionary)?.value(forKey: "small") as? String)!)
let data = try? Data(contentsOf: url!)
}
}
catch
{
print"error"
}
}.resume()