Swift中的对象序列化:Codable、NSCoding和JSONEncoder

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Swift中的对象序列化(iOS/macOS)

序列化是将复杂对象(结构体、类、实例)转换为便于存储或网络传输的格式(JSON、Property List、二进制数据)的过程。反序列化是从这些数据中恢复对象的逆向过程。在用于iOS和macOS的Swift中,有两种主要方法:现代协议Codable(及其组成部分Encodable和Decodable)以及来自Foundation框架的较旧协议NSCoding。在本文中,我们将通过代码示例详细分析这两种方法。



1. Codable协议(推荐方式)

Codable是一个结合了Encodable和Decodable的协议。如果结构体或类的所有属性也都遵循Codable(字符串、数字、日期、数组、字典等),它可以自动生成序列化和反序列化的代码。



1.1. 基本JSON序列化

考虑一个简单的用户结构体:

import Foundation

struct User: Codable { let id: Int var name: String var email: String}

// 创建实例let user = User(id: 1, name: "伊万·彼得罗夫", email: "ivan@example.com")

// 序列化为Data(JSON)let encoder = JSONEncoder()encoder.outputFormatting = .prettyPrinted // 为了可读性输出

do { let jsonData = try encoder.encode(user) if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) }} catch { print("序列化错误:\\(error.localizedDescription)")}


1.2. 从JSON反序列化

// 假设我们有一个JSON字符串let jsonString = """{    "id": 2,    "name": "玛丽亚·斯米尔诺娃",    "email": "maria@test.com"}"""

let jsonData = Data(jsonString.utf8)let decoder = JSONDecoder()

do { let decodedUser = try decoder.decode(User.self, from: jsonData) print("姓名:\\(decodedUser.name), 邮箱:\\(decodedUser.email)")} catch { print("反序列化错误:\\(error.localizedDescription)")}


1.3. 自定义键(CodingKeys)

如果Swift中的属性名称与JSON中的键不同,请使用CodingKeys枚举:

struct Article: Codable {    var title: String    var body: String    var publicationDate: Date

enum CodingKeys: String, CodingKey { case title case body case publicationDate = "published_at" // JSON中的键 }}

let articleJSON = """{"title":"Swift Codable","body":"文章正文","published_at":"2024-01-15T10:00:00Z"}"""let articleData = Data(articleJSON.utf8)let decoder = JSONDecoder()decoder.dateDecodingStrategy = .iso8601 // 为了正确解析日期

if let article = try? decoder.decode(Article.self, from: articleData) { print("标题:\\(article.title), 日期:\\(article.publicationDate)")}


1.4. PropertyListEncoder / PropertyListDecoder

要序列化为Property List格式(XML或二进制),请使用PropertyListEncoder:

let plistEncoder = PropertyListEncoder()plistEncoder.outputFormat = .xml

if let plistData = try? plistEncoder.encode(user) { // plistData可以保存到文件 let plistString = String(data: plistData, encoding: .utf8) print(plistString ?? "无效数据")}


2. NSCoding协议(适用于继承自NSObject的类)

NSCoding是来自Objective-C的协议,至今仍用于类的序列化,特别是那些与UIKit/AppKit(例如UIView、UIViewController)一起工作的类。它要求类继承自NSObject并实现encode(with:)和init?(coder:)方法。



2.1. 使用NSCoding的类示例

                    

推荐