在 Swift 中处理 JSON:解析与序列化
JSON(JavaScript Object Notation)已成为移动和桌面应用中客户端与服务器之间数据交换的事实标准。在 Swift(iOS/macOS)生态系统中,JSON 处理实现了最高水平——从简单的 JSONSerialization 到强大的 Codable 协议。在本文中,我们将详细讲解在 Swift 中解析和序列化 JSON 的所有主要方法,提供实际示例,并展示如何避免典型错误。
1. Swift 中 JSON 处理基础:JSONSerialization
在 Swift 4 出现之前,处理 JSON 的主要工具是 Foundation 框架中的 JSONSerialization 类。它可以将 JSON 数据转换为 Swift 对象(字典、数组、字符串、数字),反之亦然。如果您需要对过程进行完全控制,或者处理遗留代码,这种方法仍然适用。
使用 JSONSerialization 解析 JSON
假设我们从服务器收到一个 JSON 字符串:
let jsonString = """{ "name": "Иван", "age": 30, "isPremium": true, "hobbies": ["чтение", "бег", "программирование"]}"""
guard let jsonData = jsonString.data(using: .utf8) else { fatalError("Ошибка кодирования строки в Data")}
do { if let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] { let name = jsonObject["name"] as? String ?? "" let age = jsonObject["age"] as? Int ?? 0 let isPremium = jsonObject["isPremium"] as? Bool ?? false let hobbies = jsonObject["hobbies"] as? [String] ?? [] print("Имя: \\(name), Возраст: \\(age), Премиум: \\(isPremium), Хобби: \\(hobbies)") }} catch { print("Ошибка парсинга JSON: \\(error.localizedDescription)")}这种方法的缺点是需要手动进行类型转换和处理可选值。代码变得冗长且容易出错。
使用 JSONSerialization 序列化为 JSON
反向过程——将 Swift 字典转换为 JSON 数据:
let personDict: [String: Any] = [ "name": "Мария", "age": 25, "isPremium": false, "hobbies": ["рисование", "йога"]]
do { let jsonData = try JSONSerialization.data(withJSONObject: personDict, options: .prettyPrinted) if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) }} catch { print("Ошибка сериализации: \\(error.localizedDescription)")}.prettyPrinted 选项使输出对人类可读。对于生产环境,通常使用 [](无格式化)以节省流量。
2. 现代方法:Codable 协议和 JSONDecoder
从 Swift 4 开始,得益于 Codable 协议(它结合了 Encodable 和 Decodable),JSON 处理变得简单得多。您只需描述数据结构,编译器就会自动生成编码/解码的代码。
使用 JSONDecoder 解析 JSON
为我们的 JSON 定义模型:
struct Person: Codable { let name: String let age: Int let isPremium: Bool let hobbies: [String]}
let jsonString = """{ "name": "Иван", "age": 30, "isPremium": true, "hobbies": ["чтение", "бег", "программирование"]}"""
guard let jsonData = jsonString.data(using: .utf8) else { fatalError("Ошибка кодирования строки")}
do { let person = try JSONDecoder().decode(Person.self, from: jsonData) print("Имя: \\(person.name), Возраст: \\(person.age), Премиум: \\(person.isPremium), Хобби: \\(person.hobbies)")} catch { print("Ошибка декодирования: \\(error.localizedDescription)")}如您所见,代码变得简洁得多。所有类型转换和检查