跳至內容

JSON 轉 Go

從 JSON 範例生成帶 json 標籤的 Go struct。

輸入

這個工具的用途

從 JSON 樣本產生帶 json:"…" tag 的 Go struct。每個物件成為 struct、每個鍵 成為 Go 風格命名的欄位(created_at CreatedAt),JSON tag 保留原始鍵名。可為 null 的值使用 指標型別(*string),讓你能區分「缺失」與「零值」。 底層使用 quicktype, 完全在你的瀏覽器內運作。

使用步驟

貼上 JSON(或載入範例),即可在右側讀到 Go struct。每個巢狀物件成為 各自的型別,欄位名為 Go 慣用大駝峰、附 json: tag, 讓 struct 可透過 encoding/json 來回。

輸入: {"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}

輸出(Go):

type Root struct {
    ID           int64         `json:"id"`
    Name         string        `json:"name"`
    CreatedAt    string        `json:"createdAt"`
    Stars        int64         `json:"stars"`
    Public       bool          `json:"public"`
    Contributors []Contributor `json:"contributors"`
    Homepage     interface{}   `json:"homepage"`
}

type Contributor struct {
    Login   string `json:"login"`
    Commits int64  `json:"commits"`
    Admin   bool   `json:"admin"`
}

限制與邊界情況

  • 欄位名是大駝峰(Go 對 exported 欄位的要求), 但 json:"…" tag 保留原始 JSON casing—— 因此 JSON 中的 created_at 變為 CreatedAt string `json:"created_at"`
  • 樣本中為 null 的欄位會輸出為 interface,而非指標。通常你會想要指標 (*string)以區分「缺失」與「零值」; 可在選項面板切換 nullable as pointer
  • 所有整數都以 int64 標型,與大小無關。若 JSON 含 2.0 則為 float64;含 2 則為 int64encoding/json 解碼時兩者皆容忍, 但對你確定永遠為整數的欄位請手動收緊。
  • 日期字串(ISO 8601)會輸出為 string,而非 time.Time。產生器無法在 JSON 層分辨日期與一般 slug—— 若想要原生時間值,請手動改型別並加上 UnmarshalJSON
  • 預設不加 omitempty tag。對於需要在序列化回 JSON 時 略過的欄位請手動加上(或切換 all optional 套用全部欄位)。
  • 單樣本限制同樣適用——樣本中不存在的鍵需手動補上或透過 all optional

常見問題

為什麼欄位名是大駝峰,但 JSON 是 camelCase?
Go 要求外部可見(首字大寫)的欄位才能讓宣告 package 以外的套件存取——`encoding/json` 就在外部,所以未匯出欄位無法序列化。`json:"camelCaseKey"` tag 保留原始 JSON 鍵供序列化使用;Go 端的名稱遵循語言慣例的大駝峰。
Nullable 欄位該用 *string 還是 interface{}?
通常指標較好:`*string` 能區分「欄位缺失」(nil 指標)與「欄位存在但為空」(指向空字串的指標)。`interface{}` 可行但失去型別安全,每次讀取都要 type assertion。可在選項面板切換「nullable as pointer」全域改變。
大數字會失去精度嗎?
數字先經過 JavaScript(瀏覽器解析 JSON 用的),因此 ±2^53 以外的值在到達 Go 產生器前就已失去精度。若 JSON 含 64-bit ID(如 Twitter/X status ID),producer 應將其序列化為字串,然後 Go 欄位加上 `json:",string"` tag,讓它能透過 encoding/json 來回。產生器無法從樣本偵測這點。
可以自動為每個欄位加上 omitempty 嗎?
可以——在選項面板切換「all optional」。產生器會為每個欄位輸出 `json:"name,omitempty"`,encoding/json 在 marshal 時會略過零值欄位。注意:`omitempty` 把 Go 的零值(0、""、false、nil)視為可省,可能會丟掉合法的值。若需要區分「零」與「省略」,請改用指標型別。
JSON 日期可以變成 time.Time 嗎?
不會自動。JSON 的日期是字串,產生器不會嘗試從任意 slug 形狀的字串認出 ISO 8601。請手動把欄位型別從 `string` 改為 `time.Time`;encoding/json 隨即以 RFC 3339 格式解析。非 RFC-3339 的日期請在 wrapper type 上實作自訂 `UnmarshalJSON`。
輸出能通過 goimports / gofmt 嗎?
可以——輸出符合 gofmt(tab 縮排、struct tag 對齊)。若你在程式碼中序列化這些 struct,goimports 可能會加上 `encoding/json` import,但產生器本身不包含未使用的 import。若編輯器沒有自動執行,可手動 `goimports -w`。

內容審閱者: