在 Swift 中,序列化 (Serialization)是将对象或数据结构转换为可以存储或传输的格式的过程。最常见的用途是将对象转换为 JSON 或者 Plist 格式,以便将其保存到文件、发送到服务器,或者从网络响应中解析。
Swift 提供了几种方式进行序列化和反序列化,其中最常见的是使用 Codable
协议和 JSONEncoder
/ JSONDecoder
来处理 JSON 数据。下面是关于 Swift 中序列化的详细介绍。
1. 使用 Codable
进行 JSON 序列化
Codable
是 Swift 提供的一个协议,它结合了 Encodable
和 Decodable
协议,使得对象可以很方便地进行序列化(编码)和反序列化(解码)。通过实现 Codable
协议,结构体或类可以轻松地与 JSON 进行互操作。
示例:定义 Codable
结构体
Copy struct User: Codable {
var name: String
var age: Int
var email: String
}
在这个例子中,User
结构体自动遵循 Codable
协议,Swift 会为其生成序列化和反序列化代码。
示例:序列化(对象转 JSON)
Copy let user = User(name: "Alice", age: 25, email: "alice@example.com")
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted // 格式化输出以便更容易阅读
if let jsonData = try? encoder.encode(user) {
if let jsonString = String(data: jsonData, encoding: .utf8) {
print(jsonString)
}
}
输出结果:
Copy {
"name" : "Alice",
"age" : 25,
"email" : "alice@example.com"
}
示例:反序列化(JSON 转对象)
Copy let jsonString = """
{
"name": "Alice",
"age": 25,
"email": "alice@example.com"
}
"""
if let jsonData = jsonString.data(using: .utf8) {
let decoder = JSONDecoder()
if let user = try? decoder.decode(User.self, from: jsonData) {
print(user)
}
}
输出结果:
Copy User(name: "Alice", age: 25, email: "alice@example.com")
2. 使用 Codable
进行 Plist 序列化
除了 JSON,Swift 还可以使用 Codable
协议将对象序列化为 Plist 格式(属性列表)。Plist 是一种 XML 格式,常用于在 iOS 和 macOS 中存储数据。
示例:Plist 序列化
Copy let encoder = PropertyListEncoder()
encoder.outputFormat = .xml
if let plistData = try? encoder.encode(user) {
if let plistString = String(data: plistData, encoding: .utf8) {
print(plistString)
}
}
输出结果(Plist 格式):
Copy <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>age</key>
<integer>25</integer>
<key>email</key>
<string>alice@example.com</string>
<key>name</key>
<string>Alice</string>
</dict>
</plist>
示例:Plist 反序列化
Copy let decoder = PropertyListDecoder()
if let userFromPlist = try? decoder.decode(User.self, from: plistData) {
print(userFromPlist)
}
3. 自定义编码和解码
有时候,自动生成的 Codable
实现不能满足需求(例如,字段名不同或需要进行某些转换)。在这种情况下,你可以通过实现 Encodable
和 Decodable
协议来自定义序列化和反序列化过程。
示例:自定义编码和解码
Copy struct User: Codable {
var name: String
var age: Int
var email: String
enum CodingKeys: String, CodingKey {
case name
case age
case email = "user_email" // 将 "email" 映射到 "user_email"
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
try container.encode(age, forKey: .age)
try container.encode(email, forKey: .email)
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
age = try container.decode(Int.self, forKey: .age)
email = try container.decode(String.self, forKey: .email)
}
}
在这个例子中,email
字段在 JSON 中表示为 user_email
,但在代码中仍然使用 email
字段。通过自定义 CodingKeys
枚举,可以将 JSON 的字段名映射到结构体的属性名。
4. 使用 NSCoding
进行序列化
在一些需要与 Objective-C 兼容的场景下,Swift 也可以使用 NSCoding
协议进行序列化。NSCoding
主要用于归档和解档对象。
示例: NSCoding
序列化
Copy class Person: NSObject, NSCoding {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
required init?(coder aDecoder: NSCoder) {
name = aDecoder.decodeObject(forKey: "name") as! String
age = aDecoder.decodeInteger(forKey: "age")
}
func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: "name")
aCoder.encode(age, forKey: "age")
}
}
5. 使用 Codable
序列化嵌套对象
当你的对象中包含其他对象时,Codable
也能处理嵌套的结构。
示例:嵌套对象的序列化
Copy struct Address: Codable {
var street: String
var city: String
}
struct User: Codable {
var name: String
var age: Int
var address: Address
}
let address = Address(street: "123 Main St", city: "New York")
let user = User(name: "Alice", age: 25, address: address)
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(user),
let jsonString = String(data: jsonData, encoding: .utf8) {
print(jsonString)
}
6. 错误处理
在序列化和反序列化过程中,可能会出现错误,比如数据格式不匹配或丢失。Swift 使用 try
、catch
处理这些错误。
示例:错误处理
Copy do {
let jsonData = try encoder.encode(user)
} catch {
print("Failed to encode user: \(error.localizedDescription)")
}
总结
Swift 提供了强大且灵活的序列化功能,最常用的是通过 Codable
处理 JSON 和 Plist 数据。通过使用 Codable
,开发者可以轻松地在对象和外部数据格式之间进行转换,并且 Swift 提供了自定义编码和解码的选项来处理更复杂的数据结构。
Last updated 7 months ago