John Montgomery
John Montgomery

Reputation: 7096

Guard not unwrapping optional

I'm trying to process a JSON object, using a guard statement to unwrap it and cast to the type I want, but the value is still being saved as an optional.

guard let json = try? JSONSerialization.jsonObject(with: data) as? [String:Any] else {
    break
}

let result = json["Result"]
// Error: Value of optional type '[String:Any]?' not unwrapped

Am I missing something here?

Upvotes: 8

Views: 1031

Answers (1)

Martin R
Martin R

Reputation: 539695

try? JSONSerialization.jsonObject(with: data) as? [String:Any]

is interpreted as

try? (JSONSerialization.jsonObject(with: data) as? [String:Any])

which makes it a "double optional" of type [String:Any]??. The optional binding removes only one level, so that json has the type [String:Any]?

The problem is solved by setting parentheses:

guard let json = (try? JSONSerialization.jsonObject(with: data)) as? [String:Any] else {
    break
}

And just for fun: Another (less obvious?, obfuscating?) solution is to use pattern matching with a double optional pattern:

guard case let json?? = try? JSONSerialization.jsonObject(with: data) as? [String:Any] else {
    break
}

Upvotes: 13

Related Questions