這個工具的用途
使用步驟
貼上 JSON(或載入範例),即可在右側讀到 Swift struct。每個巢狀物件 成為各自的 Codable struct;當 JSON 鍵與 Swift 屬性名相符 時,輸出可直接給 Foundation 的 JSONDecoder 使用, 無需額外註解。
輸入: {"id":42,"name":"devsmiths","createdAt":"2024-03-11T08:24:00Z","stars":1280,"public":true,"contributors":[{"login":"ada","commits":51,"admin":true},{"login":"linus","commits":33,"admin":false}],"homepage":null}
輸出(Swift):
import Foundation
struct Root: Codable {
let id: Int
let name: String
let createdAt: String
let stars: Int
let `public`: Bool
let contributors: [Contributor]
let homepage: String?
}
struct Contributor: Codable {
let login: String
let commits: Int
let admin: Bool
}限制與邊界情況
- 輸出採
struct並符合Codable, 不是class。struct 是 Swift 的 value type—— 適合 JSON DTO。若需要 reference 語意(例如 SwiftUI 的@ObservableObject),請手動以 class 包裹。 - 屬性為
let(不可變)。需要修改時透過var copy = original重建,或手動把真的會被修改的欄位 改為var。 - Swift 保留字(
public、class、default)作為 JSON 鍵時,會在 Swift 原始碼中以反引號 包覆(let `public`: Bool);JSONDecoder 看到的是原始鍵。 - camelCase / snake_case 不一致:預設不產生
CodingKeysenum,因此 JSON 鍵必須與 Swift 屬性名字元對字元相符。snake_case JSON 請設定decoder.keyDecodingStrategy = .convertFromSnakeCase, 不必為每個 struct 顯式產生CodingKeys。 - 日期字串保持為
String。請設定decoder.dateDecodingStrategy = .iso8601並手動把屬性 改為Date——JSONDecoder沒有 per-field 日期策略。 - 單樣本推論:樣本中不存在的鍵不會自動變 Optional。 切換 all optional 套用全部欄位。
常見問題
- 為什麼是 struct + Codable 而不是 class?
- struct 是 Swift 的 value type,作為 JSON DTO 完全合適——複製語意、無 reference cycle、建構上是 thread-safe。Codable 是 stdlib protocol(Encodable + Decodable),JSONDecoder / JSONEncoder 都對它操作。需要 reference 語意時(SwiftUI 的 @ObservedObject、持久化),請手動以 class 包裹 struct 或在 wrapper 上使用 @Observable。
- 如何處理 camelCase JSON vs snake_case JSON 鍵?
- JSONDecoder 有 `keyDecodingStrategy`。snake_case JSON:`decoder.keyDecodingStrategy = .convertFromSnakeCase`。產生的 struct 使用 camelCase 屬性名(Swift 慣例);策略自動架橋。若大小寫混雜或鍵不遵循任一慣例,請為各 struct 顯式產生 `CodingKeys` enum——產生器預設不這麼做,因為全域策略通常已足夠。
- Date 欄位可以變成 Date 而非 String 嗎?
- 可以,兩步。把產生的 struct 中的 String 改為 Date,設定 `decoder.dateDecodingStrategy = .iso8601`(或 `.formatted(...)` 處理非 ISO 格式)。dateDecodingStrategy 是 decoder 全域——每個 Date 屬性都同等對待。若需要 per-field 控制,寫自訂 `init(from:)` 個別處理每個 Date 欄位。
- 為什麼我的 JSON 鍵 public 被反引號包覆?
- 因為 `public` 是 Swift 存取修飾字。反引號讓你可以把保留字當識別字使用(`let `public`: Bool`)而不必重新命名。JSONDecoder 看到原始鍵(`public`)並繫結到被反引號包覆的 Swift 屬性。若偏好重新命名,加 `CodingKeys` enum:`case isPublic = "public"`,使用 `isPublic` 作為 Swift 端名稱。
- 完全不是合法 Swift 識別字的 JSON 鍵怎麼辦?
- 含連字號或開頭為數字的鍵(`2024-tax-year`)即使加反引號也無法當 Swift 屬性名。請使用顯式 `CodingKeys` enum:`case taxYear = "2024-tax-year"`,以 `taxYear` 作為 Swift 端名稱。當 JSON 鍵在任何逸出下都不合法時,產生器會自動輸出 CodingKeys enum。
- 產生的 struct 可以配 SwiftData / Core Data 使用嗎?
- 不能直接配。兩個框架都要 `@Model`(SwiftData)或 `NSManagedObject`(Core Data)基底類別——這是帶持久化機制的 reference type。產生的 struct 是純 value type。請將其作為 DTO 層使用(解析 JSON → struct → 傳給映射函式 → 寫入 SwiftData model)。單向映射讓解析層快、持久化層意圖明確。
內容審閱者:ShiangYu Huang