Swift-使用 Codable 归档 Swift 对象

4,817 阅读2分钟
struct User {

    let firstName: String
    let lastName: String
}  

当处理这样的数据时,Swift 为我们提供了一个奇妙的协议,称为Codable:专门用于归档和取消归档数据的协议,这是“将对象转换为纯文本并再次转换回来”的一种奇特方式。

我们想要存档自定义类型,以便我们可以将其放入 UserDefaults中,然后在它从UserDefaults 返回时取消存档

  • 遵守协议

遵守协议后,Swift 会自动为我们生成一些代码,根据需要为我们归档和取消归档User实例

struct User: Codable {

    let firstName: String
    let lastName: String
} 
  • 归档:将对象数据 转换为 JSON 数据
if let data = try? JSONEncoder().encode(user) {

    UserDefaults.standard.set(data, forKey: "UserData")
}  

使用的JSONEncoder().encode()意思是“创建一个编码器并使用它来编码某些内容”,这一切都在一个步骤中,而不是先创建编码器然后再使用它。

这可能会引发错误,因此应该使用try或try?来调用它以巧妙地处理错误。

  • 解档
if let data = UserDefaults.standard.data(forKey: "xxxKey") {
    if let decData = try? JSONDecoder().decode([ExpenseItem].self, from: data){
        items = decData
        return
    }
}

其中,decode方法需要传入 解档数据的类型

JSON嵌套

解码稍微复杂的 JSON:一个数组位于另一个数组中,使用不同的数据类型。如果您想解码这种分层数据,关键是为每个级别创建单独的类型。只要数据与您要求的层次结构相匹配,Codable就能够解码所有内容,而无需我们进行进一步的工作。

如下数据:

{
    "name": "Taylor Swift",
    "address": {
        "street": "555, Taylor Swift Avenue",
        "city": "Nashville"
    }
}  

创建两个结构体,并且均遵守Codable协议

struct User: Codable {

    let name: String
    
    let address: Address
}



struct Address: Codable {

    let street: String
    let city: String
} 

接着,处理数据。先将 JSON 字符串转换为类型Data(这是Codable适用的),然后将其解码为User实例:

let data = Data(jsonString.utf8)

let decoder = JSONDecoder()

if let user = try? decoder.decode(User.self, from: data) {

    print(user.address.street)

}  

嵌套结构体

image.png