Swift Codable 與 JSON 解析
在現代 App 開發中,處理 JSON 資料是家常便飯。Swift 4 推出的 Codable 協議讓這個過程變得異常簡單與優雅。
Codable 是一個複合協議 (Type Alias),它同時包含了 Encodable (編碼) 和 Decodable (解碼)。
typealias Codable = Encodable & Decodable
基本使用
假設你有以下的 JSON 資料:
{
"name": "Durian",
"points": 600,
"description": "A fruit with a distinctive smell."
}
你可以定義一個遵循 Codable 的 Struct 來對應它:
struct GroceryProduct: Codable {
var name: String
var points: Int
var description: String?
}
JSON 解碼 (Decoding)
使用 JSONDecoder 將 JSON 資料 (Data) 轉換成 Swift 物件。
let json = """
{
"name": "Durian",
"points": 600,
"description": "A fruit with a distinctive smell."
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
do {
let product = try decoder.decode(GroceryProduct.self, from: json)
print(product.name) // 輸出 "Durian"
} catch {
print("解析失敗:\(error)")
}
JSON 編碼 (Encoding)
使用 JSONEncoder 將 Swift 物件轉換回 JSON 資料。
let product = GroceryProduct(name: "Banana", points: 200, description: "A yellow fruit")
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted // 讓輸出的 JSON 縮排美觀
do {
let data = try encoder.encode(product)
let jsonString = String(data: data, encoding: .utf8)!
print(jsonString)
} catch {
print("編碼失敗:\(error)")
}
自訂對應鍵 (CodingKeys)
後端 API 回傳的欄位名稱通常是 snake_case (如 first_name),但 Swift 的慣例是 camelCase (如 firstName)。
你可以透過在 Struct 內定義一個名為 CodingKeys 的列舉來解決這個問題:
struct User: Codable {
var firstName: String
var lastName: String
var age: Int
// 定義 JSON Key 與 Property 的對應關係
enum CodingKeys: String, CodingKey {
case firstName = "first_name"
case lastName = "last_name"
case age // 名字一樣的可以不用寫 = rawValue
}
}
這樣 JSONDecoder 就會自動幫你轉換了。
你也可以設定 decoder.keyDecodingStrategy = .convertFromSnakeCase 來自動處理,但使用 CodingKeys 提供了最精確的控制。
處理日期 (Date Handling)
JSON 標準中並沒有定義日期的格式,通常是 ISO 8601 字串或 Timestamp。你可以設定 dateDecodingStrategy 來告知 Decoder 如何解析日期。
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601 // 處理 "2024-02-07T09:10:00Z"
Swift 的 Codable 非常強大,可以處理巢狀結構、多型以及各種複雜的資料格式,是處理網路資料的首選方案。