Casting in Swift doesn't work as expected

Originator:mihirpmehta
Number:rdar://32072227 Date Originated:09-May-2017 03:54 PM
Status:Open Resolved:No
Product:iOS + SDK Product Version:10.3.1
Classification:Core Foundation Reproducible:Everytime
 
I have created a custom protocol,which i am planning to use in place of Any

But i doesn't work when i try to cast it from JSONSerialization.jsonObject

import Foundation
import CoreFoundation
//MARK:- Protocol
public protocol StringOrNumber {}

//MARK:- Protocol Extension
extension String:StringOrNumber {}
extension NSNumber:StringOrNumber {}
extension Bool:StringOrNumber {}
extension Float:StringOrNumber {}
extension Int32:StringOrNumber {}
extension Int64:StringOrNumber {}
extension Int:StringOrNumber {}
extension Double:StringOrNumber {}
extension Dictionary:StringOrNumber {}
extension Array:StringOrNumber {}
extension NSDictionary:StringOrNumber {}
extension NSArray:StringOrNumber {}
extension NSString:StringOrNumber {}
extension NSNull:StringOrNumber {}

//MARK:- Code
private func readJson() {
    let d = ["first":"john", "last":"doe"] as [String:Any]
    if let data = try? JSONSerialization.data(withJSONObject: d, options: []) {
        
        if let json = try? JSONSerialization.jsonObject(with: data, options: []) {
            // This Code Works ↓ ↓ ↓ ↓ ↓
            if let object = json as? [String: Any] {
                // json is a dictionary
                print("Hello World: \(object)")
                if let newObject:[String:StringOrNumber] = object as? [String:StringOrNumber] {
                    // json is a newer dictionary
                    print(newObject)
                }
            }
            //This Code Doesn't work ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
            let object:[String: StringOrNumber]? = json as? [String: StringOrNumber]
            // json is a dictionary
            print(object ?? "Dictionary is Empty")
        }
    }
}
readJson()

I don't understand why the first piece of code doesn't works and 2nd one does ...

Thanks

Comments

Because downcasting can fail

Use optional value of the type you are trying to downcast to.

let object:[String: StringOrNumber?]? = json as? [String: StringOrNumber?] // json is a dictionary print(object ?? "Dictionary is Empty")

It will print below: ["first": Optional(john), "last": Optional(doe)]

By gauswami.mayur at June 19, 2017, 9:47 a.m. (reply...)

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!