JSON 轉 Go 結構體轉換器
貼上一個 JSON 物件(或 JSON 陣列),自動生成對應的 Go struct 定義及 json 標籤。
從 JSON 產生 Go 結構體
要在 Go 裡接收 API 回應,就得寫出與該 JSON 對應的結構體及其 json 標籤。欄位只有幾個時並不費事,可一旦巢狀加深,邊想型別名稱邊順著層級走,本身就成了負擔。 本工具只需您貼入 JSON,便會連同巢狀結構一併產生整套定義。
不過請記住,產出的是「由一份樣本推斷出的型別」。 樣本中未出現的鍵自然不會有,而值為 null 的欄位會變成 interface{},因為 Go 並無可對應的可空基本型別。若陣列的元素全是物件,則各元素的鍵會合併為一個結構體,只在部分元素中出現的鍵會被標上 omitempty。 要把輸出變成可用於生產的結構體,前提是您會拿這些推斷去對照真正的 API 規格並加以訂正。
轉換的步驟
- 貼入 JSON 物件或陣列皆可,API 回應可原樣貼入。
-
給根型別命名
初始為
Root。巢狀型別的名稱由各屬性名轉為帕斯卡命名法自動得出。 - 查看產生的結構體 定義會按層級順序排列,json 標籤一併就位。
-
複製出來再整理
先過一遍
gofmt,再依真實規格訂正變成interface{}的地方,以及該用指標的地方。
用好本工具的小技巧
- 當陣列的所有元素都是物件時,會合並各元素的鍵生成一個 struct。僅存在於部分元素中的鍵會自動加上
omitempty標籤。 - 根型別名稱預設是 "Root",可以改成你喜歡的名字。巢狀物件的 struct 名稱會根據屬性名自動轉換為 PascalCase 生成。
- 由於 Go 沒有原生的可空基本型別,JSON 的 null 會被轉換為
interface{}。如需更嚴格的處理,可以考慮改用指標型別。 - 生成結果只是簡單對齊列寬的草稿,粘貼後通過
gofmt處理即可對齊到專案的標準風格。 - 直接貼上 API 響應的示例 JSON,即可快速得到 Go 中響應結構體的初稿。
這些情境會用到
著手寫 API 用戶端時
把文件裡的範例回應貼上,馬上就有一份接收用結構體的初稿。
讀取設定檔時
設定以 JSON 保存時,可把其結構直接謄寫成型別。
讀懂第三方規格時
層層巢狀的 JSON,一旦攤開成結構體便容易把握得多。
準備測試夾具時
先由真實回應推出型別,寫模擬資料時便少了張冠李戴之虞。
Go 型別對應的術語
- 結構體
- Go 中把若干欄位聚在一起的型別,對應 JSON 裡的物件。
- json 標籤
- 寫在欄位之後、形如
json:"user_id"的註解,它告訴編碼器 Go 的欄位名與 JSON 的鍵如何對齊。 - omitempty
- 寫在 json 標籤中的選項,當值為空(false、0、空字串、nil、長度為 0 的切片或映射)時,從輸出中省略。 需要注意結構體型別的欄位即使是零值也不會被省略,而且它並不表示可為 null。
- interface{}
- 可接納任意值的型別。JSON 的 null 與型別多變的欄位會落到這裡,因而成了產生後需回頭查看之處的標記。
- 帕斯卡命名法
- 每個單字首字母大寫的寫法,如
UserId。在 Go 中這個開頭的大寫還兼有從套件中匯出的含義。 - 指標型別
- 寫作
*string的型別。當「沒有值」必須與「空字串」區分開來時,便要用它。
常見問題
json:"原始鍵")中,因此編碼解碼不受影響。以日文等無法轉為大寫的字元開頭的鍵會加上 Field 前綴(例如 名前 → Field名前),轉換後名稱相同的鍵(如 user_id 與 userId)則在末尾加上序號,確保產生的名稱互不重複、能在 Go 中編譯通過。interface{} 型別。僅在陣列部分元素中出現的鍵會自動帶上 omitempty 標籤,但 Go 型別本身只會取零值,如需區分"缺失"與"零值",可以考慮改用指標型別。1.0、1e3)時判斷為 float64,兩者都沒有時判斷為 int。Go 的 encoding/json 無法把含小數點或指數的數值讀入整數型別,因此這樣區分。超出 64 位元環境下 int 範圍(約 ±9.2×10^18)的整數會設為 float64,以免讀取失敗。不過 float64 會捨入位數,如需精確處理較大的 ID 等,請考慮改用 json.Number 或 string。interface{},需要在執行時用型別斷言來判斷實際的值型別。
閒話 ― Go 中 struct 與 json 標籤的設計
Go 是一門靜態型別語言,在處理 JSON 時,標準庫的 encoding/json 包依賴 struct 欄位與 json 標籤之間的對應關係來完成編碼和解碼。手工為外部 API 的響應結構編寫 struct 是一項隨著欄位增多而愈發繁瑣的重複勞動,這在許多 Go 專案中反覆出現。
這款工具通過解析示例 JSON 的結構,自動生成對應的 struct 定義和 json 標籤,從而減輕這類重複工作。同類工具中,支援轉換為多種語言型別的 quicktype 頗為知名;但如果只是想貼上一份示例 API 響應、快速得到一個 Go struct,專注單一功能的工具也自有其便利之處。
由於 Go 沒有讓 struct 欄位變為"可選"的語言特性,對於 JSON 中可能缺失的欄位,常見做法是在 json 標籤中加上 omitempty,或改用指標型別(如 *string)來區分零值與"值不存在"。生成的 struct 終究只是根據結構做出的機械推斷,將可空性判斷和 API 未來變化納入設計,應當對照實際的介面文件手動調整,這是實踐中的通行做法。