Parsing value with try? and guard returning different values [duplicate] - swift

This question already has answers here:
Optional binding with try? and as? still produces an optional type
(2 answers)
Closed 5 years ago.
Language Used: Swift 3
Xcode Version: 8.3.2 (8E2002)
I have an extension on Data which parses the data into a JSONObject of type Any
extension Data {
func toJsonObject() -> Any? {
do {
return try JSONSerialization.jsonObject(with: self, options: [])
} catch {
print(error)
}
return nil
}
}
Now the weird thing is when I use guard the result object seems to be different when using toJsonObject() and try?
For example
guard let dictionary = data.toJsonObject() as? [String: Any] else {
return
}
dictionary is now of type [String: Any]
Whereas when I use this:
guard let dictionary = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
return
}
dictionary is now of type [String: Any]?
Isn't the result of the second code block supposed to be [String: Any] instead of the optional [String: Any]?
Is this a mistake on Swift or am I doing something wrong?

This is a feature of Swift, I'd say. The use of try? means that this becomes a double optional, it's trying to decode straight to that casting of as? [String: Any]. Plug this in and check the type on this to see the double optional in action:
// Becomes a type of `[String : Any]??`
let dictionary = try? JSONSerialization.jsonObject(with: Data(), options: []) as? [String: Any]
I think the answer you want is to just add some parentheses to clarify your intent:
guard let dictionary = (try? JSONSerialization.jsonObject(with: Data(), options: [])) as? [String: Any] else {
return
}

Related

How to check JSON can be converted to dictionary in Swift?

Tried this, but get error:
var d = (try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers)) as [String: String]
guard let d2 = d else {
return
}
You can try
guard let dic = try? JSONSerialization.jsonObject(with: data) as? [String: String] else { return }
The right tool here is JSONDecoder, not JSONSerialization:
let d = try JSONDecoder().decode([String: String].self, data)
.mutableContainers doesn't make sense when converting to a Swift Dictionary. That causes it to create NSMutableDictionary objects, which will just be converted to [String: String] exactly the same as without .mutableContainers (but possibly with an extra copy step).

Error while parsing Json in swift 2.3

I am trying to parse this NSDictionary
{"fare":{"value":99.03,"fare_id":"12313545861568689494880005558558852","expires_at":1485864494,"display":"\u20b999.03","currency_code":"INR"},"trip":{"distance_unit":"mile","duration_estimate":720,"distance_estimate":2.76},"pickup_estimate":2}
My code is:
if let statusesArray = try? NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [[String: Any]],
let user = statusesArray![0]["fare"] as? [String: Any],
let username = user["fare_id"] as? String {
// Finally we got the username
}
else
{
print("DONE")
}
But I am not getting the value fare ID. In fact its printing "DONE" from the else statement. I tried using apple's documentation of handling data,But the same error persist.
Your JSON response is Dictionary not Array, so type cast it to [String:AnyObject] and then get fare_id from the nested fare Dictionary.
if let dict = (try? NSJSONSerialization.JSONObjectWithData(data!, options: [])) as? [String: AnyObject],
let fareDict = dict["fare"] as? [String:AnyObject]
let username = fareDict["fare_id"] as? String {
print(username)
}

Ambiguous reference to member subscript with Array<Dictionary<NSObject, AnyObject>>

I am getting this "Ambiguous reference to member subscript" error for below code -
let resultsDict = try JSONSerialization.jsonObject(with: data!, options: []) as! Dictionary<NSObject, AnyObject>
let items: Array<Dictionary<NSObject, AnyObject>> = resultsDict["items"] as! Array<Dictionary<NSObject, AnyObject>>
First of all I would not use NSObject with JSONSerialization, use [AnyHashable: Any] or [String : Any] instead. Secondly, I would recommend you use the shorthand dictionary and array syntax with brackets. I would also recommend using safe downcasts (as ?) with if let instead of forced downcasts (as!) for safety.
do {
if let resultsDict = try JSONSerialization.jsonObject(with: data!, options: []) as? [String : Any] {
let items = resultsDict["items"] as? [[String : Any]]
// use items
}
} catch {
// handle error
}

Type 'Any' has no subscript memebers [duplicate]

This question already has answers here:
Correctly Parsing JSON in Swift 3
(10 answers)
Closed 6 years ago.
When i converted to swift 3 , its saying type any has no subscript memebers.
let dataDictionary = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers)
let accessToken = dataDictionary["access_token"] as! AnyObject?
Ihave tried many possiblities but didn't worked.
The return type of JSONSerialization.jsonObject(with:options:) is Any which doesn't allow subscripting. You have to use explicit type conversion to subscript. If you're trying to cast the data to [String: Any] you could do the following:
if let dataDictionary = dataDictionary as? [String: Any] {
// dataDictionary["access_token"] as AnyObject
}
JSONSerialization.jsonObject throws an error so let catch it in a do catch block
do {
let dataDictionary = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String: Any]
let accessToken = dataDictionary["access_token"] as! AnyObject
} catch let error as NSError {
print(error)
}

How to resolve the error "ambiguous reference to member 'subscript'"

I get the error:
Ambiguous reference to member 'subscript'
On the following code:
let jsonObject = try JSONSerialization.jsonObject(with: data, options: [])
guard let jsonDictionary = jsonObject as? [NSObject: AnyObject],
let photos = jsonDictionary["photos"] as? [String: AnyObject], // this line is giving the error
let photosArray = photos["photo"] as [[String: AnyObject]] else {
print("Error")
}
Previous posts have suggested that I change the type from [String: AnyObject] to [AnyObjectHashable: Any]. This hasn't fixed the error. Can someone explain why this error is occurring and how it can be resolved?
You can replace this, for making dictionary in swift 3 you can use like [String: Any] instead of [String: AnyObject]
let jsonObject = try JSONSerialization.jsonObject(with: data, options: [])
guard let jsonDictionary = jsonObject as? [String: Any],
let photos = jsonDictionary["photos"] as? [String: AnyObject], // this line is giving the error
let photosArray = photos["photo"] as? [[String: Any]] else {
print("Error")
}
print(jsonDictionary)