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 非常強大,可以處理巢狀結構、多型以及各種複雜的資料格式,是處理網路資料的首選方案。