在 Swift (iOS/macOS) 中处理 JSON:完整指南
JSON(JavaScript 对象表示法)是现代 iOS/macOS 应用中的主要数据交换格式。Swift 提供了一套强大的 JSON 处理工具,从内置的 Codable 协议到简化解析和序列化的第三方库。本文将详细讲解在 Apple 平台的 Swift 中处理 JSON 的所有主要方法。
内置 JSON 支持:Codable(Swift 4+)
从 Swift 4 开始,Apple 引入了 Codable 协议(它结合了 Encodable 和 Decodable),允许自动将自定义数据类型转换为 JSON 或从 JSON 转换回来,无需编写样板代码。
JSON 解码基础示例
import Foundation
// 1. 定义数据模型struct User: Codable { let id: Int let name: String let email: String let isActive: Bool}
// 2. JSON 字符串let jsonString = """{ "id": 1, "name": "伊万·彼得罗夫", "email": "ivan@example.com", "isActive": true}"""
// 3. 解码if let jsonData = jsonString.data(using: .utf8) { let decoder = JSONDecoder() do { let user = try decoder.decode(User.self, from: jsonData) print("用户: \\(user.name), 邮箱: \\(user.email)") } catch { print("解码错误: \\(error.localizedDescription)") }}将对象编码为 JSON
let newUser = User(id: 2, name: "玛丽亚·西多罗娃", email: "maria@example.com", isActive: false)
let encoder = JSONEncoder()encoder.outputFormatting = .prettyPrinted // 为了可读性输出
do { let jsonData = try encoder.encode(newUser) if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) }} catch { print("编码错误: \\(error)")}处理 snake_case 键和自定义策略
通常,JSON 的键采用 snake_case 风格(例如,first_name),而 Swift 属性使用 camelCase(firstName)。只需一行代码即可解决:
decoder.keyDecodingStrategy = .convertFromSnakeCaseencoder.keyEncodingStrategy = .convertToSnakeCaseJSONSerialization —— 底层操作
对于 JSON 结构未知或需要灵活性时,可以使用 Foundation 中的 JSONSerialization:
if let jsonData = jsonString.data(using: .utf8) { do { if let jsonDict = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] { let name = jsonDict["name"] as? String ?? "" let age = jsonDict["age"] as? Int ?? 0 print("姓名: \\(name), 年龄: \\(age)") } } catch { print("错误: \\(error)") }}此方法返回 Any,因此需要进行类型转换。适用于动态数据,但类型安全性较低。
第三方库
尽管内置工具功能强大,但仍有一些流行的库可以简化 Swift 中的 JSON 处理:
1. SwiftyJSON
最流行的库之一。允许通过下标访问 JSON 元素,并自动处理可选值。
// 通过 Swift Package Manager 安装:https://github.com/SwiftyJSON/SwiftyJSONimport SwiftyJSON
let json = JSON(parseJSON: jsonString)let userName = json["name"].stringValuelet userEmail = json["email"].string ?? "未指定"print("姓名: \\(userName), 邮箱: \\(userEmail)")
// 处理嵌套对象let address = json["address"]["city"].stringValue2. ObjectMapper
用于将 JSON 映射到对象及反向映射的库。需要实