在Swift中处理JSON:解析与序列化
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,广泛应用于Web服务和移动应用中。在Apple生态系统(iOS、macOS、watchOS、tvOS)中,JSON处理是开发中不可或缺的一部分:从服务器加载数据到保存应用设置。本文将详细介绍如何使用Swift内置的Codable、JSONDecoder和JSONEncoder协议执行JSON解析(解码)和序列化(编码)。
1. Codable基础:数据模型
在Swift中处理JSON的现代方法基于Codable协议,它结合了两个协议:Encodable(用于序列化)和Decodable(用于解析)。要使您的结构体或类能够转换为JSON并反向转换,只需将其声明为Codable即可。
来看一个用户模型的示例:
struct User: Codable { let id: Int let name: String let email: String let isActive: Bool}如果JSON中的键与Swift中的属性名称不同(例如,使用snake_case而不是camelCase),您可以使用CodingKeys枚举:
struct User: Codable { let id: Int let fullName: String let email: String let isActive: Bool
enum CodingKeys: String, CodingKey { case id case fullName = "full_name" case email case isActive = "is_active" }}2. 使用JSONDecoder解析JSON
要将JSON字符串或数据转换为Swift对象,需要使用JSONDecoder。主要方法是decode(_:from:),它接受数据类型(符合Decodable)和Data对象。
解析从API获取的JSON字符串示例:
let jsonString = """{ "id": 1, "name": "伊万·彼得罗夫", "email": "ivan@example.com", "is_active": true}"""
let jsonData = Data(jsonString.utf8)
do { let decoder = JSONDecoder() let user = try decoder.decode(User.self, from: jsonData) print("用户: \\(user.name), 邮箱: \\(user.email)")} catch { print("解码错误: \\(error.localizedDescription)")}通常JSON以对象数组的形式出现。在这种情况下,只需指定类型[User].self:
let jsonArrayString = """[ {"id": 1, "name": "伊万", "email": "ivan@test.com", "is_active": true}, {"id": 2, "name": "玛丽亚", "email": "maria@test.com", "is_active": false}]"""
let jsonArrayData = Data(jsonArrayString.utf8)
do { let users = try JSONDecoder().decode([User].self, from: jsonArrayData) users.forEach { print($0.name) }} catch { print("错误: \\(error)")}3. 使用JSONEncoder将对象序列化为JSON
反向过程——将Swift对象转换为JSON——使用JSONEncoder完成。encode(_:)方法返回一个Data对象,然后可以将其转换为字符串或发送到服务器。
let user = User(id: 3, fullName: "阿列克谢·斯米尔诺夫", email: "alex@example.com", isActive: true)
do { let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted // 用于可读格式 let jsonData = try encoder.encode(user) if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) }} catch { print("编码错误: \\(error)")}输出将如下所示:
{ "id" : 3, "full_name" : "阿列克谢·斯米尔诺夫", "email" : "alex@example.com", "is_active" : true}请注意,JSO