NSKeyedUnarchiver,如何安全地解码 Any 类型

NSKeyedUnarchiver, how to decode securely the Any type

我有一组安全编码到 10.13 之前的数据文件中的字典。希望它们可以在 10.13 中通过 API 更改为 NSKeyedArchiver/NSKeyedUnarchiver 来解码。现在我无法在较新的 API 中安全地解码类型化数组 [[String: Any]]。有什么办法吗?

// the older coding method, pre 10.14 . This works on 10.14.6
let arr: [[String: Any]] = [["one": "data"],["two": Double(2.0)]]
//let arr: [[String: String]] = [["one": "data"],["two": "data2"]]
let mutableData = NSMutableData()
let archiver: NSKeyedArchiver = NSKeyedArchiver(forWritingWith: mutableData)
archiver.requiresSecureCoding = true
archiver.encode(arr, forKey: "mydata")
archiver.finishEncoding()
let unarchiver = try NSKeyedUnarchiver(forReadingWith: mutableData as Data)
let obj5 = unarchiver.decodeObject(forKey: "mydata")
unarchiver.finishDecoding()
if (obj5 != nil) {
    let dataobj = obj5 as! [[String: Any]]
    print(dataobj)
}

// the newer coding method, 10.13+ . This gives obj6 as nil on 10.14.6
let archiver2 = NSKeyedArchiver(requiringSecureCoding: true)
archiver2.encode(arr, forKey: "mydata")
let data = archiver2.encodedData
let unarchiver2 = try NSKeyedUnarchiver(forReadingFrom: data)
unarchiver2.requiresSecureCoding = true
if unarchiver2.containsValue(forKey: "mydata") {
    let obj6 = unarchiver2.decodeObject(forKey: "mydata")
    //let obj6 = unarchiver2.decodeDecodable([[String: String]].self, forKey: "mydata")
    unarchiver2.finishDecoding()
    if (obj6 != nil) {
        let dataobj = obj6 as! [[String: Any]]
        print(dataobj)
    }
    else {
        print("nogood")
    }
}
else {
    print("phoey")
}

在 10.14.6 的操场上执行时 returns:

[["one": data], ["two": 2]]
nogood

你的第二个例子的问题是你没有使用安全解码。

您实际上不需要此示例的密钥,所以让我们简化并演示如何使用根对象执行此操作:

do {
    let arr: [[String: Any]] = [["one": "data"],["two": Double(2.0)]]
    let data = try NSKeyedArchiver.archivedData(
        withRootObject: arr, requiringSecureCoding: true)
    if let output = try NSKeyedUnarchiver.unarchivedObject(
        ofClasses: [NSArray.self, NSDictionary.self], from: data)
        as? [[String:Any]] {
            print(output)
        } else {
            print("oops")
        }
} catch {
    print(error)
}

这个 安全解码,正如 unarchivedObject(ofClasses:from:) 上的文档所表明的那样。

为了完整起见,我将使用一个键来演示同样的事情,更多的是按照您的代码行:

do {
    let arr: [[String: Any]] = [["one": "data"],["two": Double(2.0)]]
    let arch = NSKeyedArchiver(requiringSecureCoding: true)
    arch.requiresSecureCoding = true
    arch.encode(arr, forKey: "mydata")
    let data = arch.encodedData
    let unarch = try NSKeyedUnarchiver(forReadingFrom:data)
    if let output = try unarch.decodeTopLevelObject(
        of: [NSArray.self, NSDictionary.self], forKey: "mydata") 
        as? [[String:Any]] {
            print(output)
        } else {
            print("oops")
        }
} catch {
    print(error)
}