這個工具的用途
使用步驟
貼上 JSON(或載入範例),即可在右側讀到 Kotlin data class。在選項 面板設定 package name 對應你的模組布局;預設輸出對不是合法 Kotlin 識別字的 JSON 鍵使用 Gson @SerializedName。
輸入: {"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}
輸出(Kotlin):
package com.devsmiths
import com.google.gson.annotations.SerializedName
data class Root(
val id: Long,
val name: String,
@SerializedName("createdAt") val createdAt: String,
val stars: Long,
val public: Boolean,
val contributors: List<Contributor>,
val homepage: String? = null,
)
data class Contributor(
val login: String,
val commits: Long,
val admin: Boolean,
)限制與邊界情況
- 輸出採
data class配 Gson@SerializedName。 要改用 kotlinx.serialization,把@SerializedName換成@SerialName、在每個 class 上加@Serializable、 importkotlinx.serialization.*。 - 屬性為
val(不可變)。需要var(例如配合 AndroidDataBinding)時請手動改——產生器偏向不可變, 因為多數 JSON DTO 解析後應該唯讀。 - Nullable 型別對樣本中為
null的欄位用String?。 搭配預設值(val homepage: String? = null)能讓 Gson 與 Moshi 在缺漏鍵時優雅處理。 - 整數一律
Long,與大小無關。小 ID 可手動改Int; Gson 與 Moshi 兩者皆可解碼。浮點預設Double。 - 日期字串保持為
String,不是java.time.Instant或kotlinx.datetime.Instant。若需型別化日期, 為 Gson 加TypeAdapter或為 kotlinx.serialization 加KSerializer。 - 單樣本推論:樣本中不存在的鍵不會自動變 nullable。all optional 會讓每個欄位變
T? = null。
常見問題
- 為什麼 Gson @SerializedName 而不是 kotlinx.serialization?
- Gson 在 Android 仍最常見(許多現有 app 都帶它)且在 JVM 上無需額外設定即可運作。kotlinx.serialization 極佳——強型別、可多平台、由 KSP 驅動——但需要在 build 加上 plugin 並在每個 class 上 `@Serializable`。要切換:把 `@SerializedName("foo")` 換成 `@SerialName("foo")`、為每個 class 加 `@Serializable`、import `kotlinx.serialization.*`。data class 形狀完全相同。
- data class 的 val——但我需要可變欄位,怎麼辦?
- 手動把 `val` 改 `var`。產生器偏向不可變,因為多數 JSON DTO 解析後即唯讀——你以 `copy(fieldName = newValue)` 取代就地變動。Android two-way DataBinding 確實需要 var;改相關欄位即可。
- 如何為缺漏鍵獲得 null-safe 反序列化?
- 結合 nullable 型別與預設值:`val homepage: String? = null`。Gson 與 Moshi 在型別為 nullable 且有預設值時,會把缺漏鍵視為 null。沒有預設值時,缺漏鍵會在 construction 時拋錯(Kotlin 的 null-safety 不允許未初始化的非 null 屬性存在)。「all optional」會在每個 nullable 欄位上輸出 `= null` 預設值。
- Long vs Int — 為什麼全用 Long?
- 與 Java 同理:JSON 數字經 JavaScript 為 64-bit double,2^53 以下的整數精確;再大就會在資料到達 Kotlin 前失去精度。Long 涵蓋安全範圍且不會意外 overflow。對你確定放得下 Int 的 ID 可手動收緊;Gson 與 Moshi 兩者皆能解碼。
- 產生的 data class 可以配 Room / Realm 使用嗎?
- Room 可以但有條件。Room 需要 `@Entity` annotation 與無參 constructor——data class 只在每個屬性都有預設值時才有。請加 `@Entity` 並為非 null 屬性提供預設值(`val id: Long = 0`)以滿足 Room。Realm 的話,產生的 class 必須繼承 RealmObject 並使用 var 屬性;請將它們作為 DTO,再映射為 RealmObject。
- 如何用產生的 data class 解析 JSON?
- Gson:`Gson().fromJson(jsonString, Root::class.java)`。Moshi:`moshi.adapter(Root::class.java).fromJson(jsonString)`。kotlinx.serialization(改裝後):`Json.decodeFromString<Root>(jsonString)`。三者皆會遵循 data class 上的 annotation。
內容審閱者:ShiangYu Huang