我大部分的日常工作都是 TypeScript 和 PHP,但背後卻有很大一部分工具 工具。dev 我圍繞它編寫的小服務是 Go,每次我連接新的 API 用戶端時,我都會遇到同樣的牆。您面前有一個 JSON 回應,您需要 Go 結構 json.Unmarshal 將解碼為。手工編寫結構以一種非常具體的方式很乏味:它並不難,只是繁瑣,而且繁瑣的位正是你犯錯的地方。所以我在該網站中建立了一個轉換器,這就是它的指南。
TL;DR: 工具 JSON to Go 結構轉換器 解析 JSON 文件並發出描述它的 Go 類型聲明。物件變成內聯結構,物件數組合併到一個結構中,每個欄位都會得到一個
json:"key"標記soencoding/json正確映射回資料。欄位名稱遵循 Go 約定,因此id成為ID和user_url成為UserURL. 將整數切換到int64,添加omitempty,並重新命名根類型。它完全運行客戶端:不上傳、不註冊、離線工作。
什麼是 JSON to Go 結構轉換器?
JSON to Go 結構轉換器將 JSON 文件轉換為描述它的 Go 類型聲明,因此您可以使用標準函式庫's 解碼相同的資料 encoding/json 打包而不是手動輸入結構。每個 JSON 物件都變成 Go 結構,每個欄位都攜帶一個 json:"key" 將其映射回原始名稱的標籤,並從值推斷標量類型。 JSON 字串變為 string,一個整數就變成了 int1、小數的數字變成 float64, true 和 false 成為 bool, 和 null 成為 interface{}.
這很有用的原因是 JSON 物件和 Go 結構描述了相同的形狀,一組具有類型化值的命名字段,但 Go 是靜態類型的,而 JSON 不是靜態類型的,因此該結構必須預先拼出每個類型。從樣本回應中導出這些類型是純力學,而跨嵌套有效負載手動完成的力學是錯誤所在的位置。轉換器確定性地進行推導,並將編譯的類型區塊交還給您。
值得明確問題的兩半,因為它們是天真的轉換器出錯的地方。第一個是命名:Go 僅對導出的欄位進行編碼,那些帶有大寫第一個字母的字段,並且社區 lint 規則希望通用首字母縮寫完全大寫。第二個是標籤: json:"..." 標籤必須保留精確的原始密鑰或 json.Unmarshal 運行時默默地跳過該字段,沒有錯誤。要么出錯,解碼返回一個充滿零值的結構,同時一切看起來都很好。該工具可以為您處理這兩個問題。
為什麼不手寫結構呢?
這是一個誠實的問題,因為對於平面三字段對象,手寫結構比打開工具更快。轉換器在不平坦的回應中佔有一席之地:包含嵌套物件、物件陣列以及二十個欄位(其中一半鍵是)的有效負載 snake_case 其中一些是縮寫詞,例如 id, url, 和 api_key.
在這樣的回應中,手寫版本有三種故障模式,我反覆點擊。您忘記匯出字段,因此它保持小寫和 encoding/json 拒絕填充它。你大寫字段但忘記了標籤,所以 UserName 尋找名為 的 JSON 金鑰 UserName 並且永遠找不到 user_name. 或者您弄錯了嵌套,當 JSON 實際上將欄位包裝在數組中時,將欄位聲明為普通結構。這些都不是編譯錯誤。它們是顯示為缺失資料的運行時意外,並且您調試其中一個資料所花費的時間比生成整個結構所花費的時間要多。
轉換器刪除所有三個。它匯出每個字段,從實鍵寫入標籤,並讀取實際的 JSON 形狀以在結構和一段結構之間做出決定。你貼上的是你得到的類型的內容。
這是一張表中的決定。
| 情況 | 使用 | 為什麼 |
|---|---|---|
| 具有兩個或三個字段的平面物件 | 手寫 | 比打開任何東西都快 |
| 具有多個欄位的嵌套 API 回應 | JSON to Go 結構轉換器 | 命名和標籤是手寫結構中斷的地方 |
| 您需要與 TypeScript 相同的形狀 | JSON 到 TypeScript 轉換器 | 相同的推論,不同的目標語言 |
| 您想要驗證模式,而不是類型 | JSON 模式產生器 | Draft-07 規則而不是 Go 類型 |
為什麼 Go 欄位名稱與我的 JSON 金鑰不同?
這第一次會讓人們絆倒,所以值得解釋而不是隱藏。去#39;s encoding/json 僅包裝元帥和非元帥 出口 結構字段,意思是名稱以大寫字母開頭的字段。 JSON 鍵喜歡 user_name 無法對應到未匯出的 user_name 字段,因此該字段必須重新命名為匯出的內容。該工具將每個單字大寫,然後轉動 user_name 進入 UserName.
最重要的是,Go 社群's lint 工具,規則開始於 golint 並生活在諸如此類的工具中 staticcheck想要用全部大寫字母寫出共同的縮寫。所以 id 成為 ID,不 Id; user_url 成為 UserURL,不 UserUrl;和 html_body 成為 HTMLBody. 轉換器知道標準的縮寫集, ID, URL, API, HTTP, JSON, UUID,其餘的,並應用它們,因此輸出會傳遞您的 CI 可能運行的短信。
使重命名安全的部分是標籤。每個欄位都有一個 json:"user_name" 標籤準確地持有原始密鑰,因此在運行時也是如此 json.Unmarshal 讀取 JSON 金鑰 user_name 並將其寫入 UserName 字段,無論重命名如何。 Go 部落格'關於 JSON 和 Go 的文章記錄了這種標記機制,這就是重命名字段仍然正確解碼的原因。如果沒有標籤,重命名的結構將悄悄地無法填充。
如何處理物件的數字和數組?
推論的兩個部分值得仔細研究,因為它們是轉換器品質不同的地方。
數字第一。 JSON 有單一數字類型,但 Go 沒有,因此工具必須選擇。沒有小數的值變成 int,或者 int64 如果開啟該選項,則小數點的值變為 float64。 有趣的情況是混合它們的數組,例如 [9.5, 8, 7.2]。 如果工具將其鍵入為 []int 它將無法解碼 9.5,所以它把整個切片拓寬到 []float64. 任何一個元素強制使用更寬類型的數組都會獲得所有元素的更寬類型,這是解碼每個值的唯一選擇。
物件數組是真實有效負載變得有趣的另一個地方。 API 幾乎從不為您提供每個物件都有一組相同金鑰的數組;一個元素有一個其他元素省略的字段,或者這裡存在一個可歸零字段,但那裡不存在。如果該工具僅從第一個元素產生結構,它將丟棄稍後出現的鍵。相反,它將數組中的每個物件合併為一個結構,其中包括任何元素所具有的每個鍵。如果兩個元素給出相同的鍵不相容類型,例如一個中的數字和另一個中的字串,則該欄位會回落到 interface{} 而不是工具猜測錯誤或徹底失敗。結果是可以解碼整個數組的單一結構類型。
如何使用轉換器?
流程分為四個步驟。將 JSON 物件或陣列貼到輸入框中;如果您想先查看輸出的形狀,請載入樣本。給根類型一個名稱,例如 User 或者 ApiResponse,該工具將其清理為有效的匯出 Go 標識符,以便它按照書面形式進行編譯。選擇 int 或者 int64 對於整數,然後打開 omitempty 如果您希望在稍後將結構編碼回 JSON 時省略零值字段。然後按一下「轉換」並將該結構複製到您的 .go 文件。
如果 JSON 無效,該工具會報告解析器'自己的錯誤訊息而不是默默失敗,因此很快就會找到雜散尾隨逗號或不引用的密鑰。由於所有內容都在您的瀏覽器中運行,因此您可以貼上真實的 API 回應,包括帶有私有欄位的回應,而無需離開您的電腦。該客戶端模型與網站其他部分後面的模型相同,如 中所述 資料隱私線上工具 指南。
這與其他 JSON 工具有何契合?
JSON to Go 結構轉換器是網站上 JSON 轉換器系列的成員之一,它們共享相同的解析核心。當您想先整理 JSON 時, JSON 格式化程式 將縮排並驗證它,這在轉換之前值得執行,以便您可以讀取要鍵入的形狀。當您的目標語言是 TypeScript 而不是 Go 時, JSON 到 TypeScript 轉換器 運行相同的推論並發出介面。當您需要驗證合約而不是語言類型時, JSON 模式產生器 產生 Draft-07 模式,當目的地是 PHP 程式碼庫時, JSON 到 PHP 陣列轉換器 寫一個數組文字。
連接所有這些主線是,他們將 JSON 視為結構來源,並將該結構翻譯成程式碼庫所說的任何內容。如果您跨多種語言工作,則 web 開發人員工具包 綜述顯示了這些片段如何組合在一起,以及 編碼工具指南 涵蓋更廣泛的格式化程式和轉換器集。
建立 Go 服務的一個有效範例
讓我具體說一下。不久前,我正在編寫一個小型 Go 服務,該服務從第三方 API 中提取資料並重新暴露其精簡版本。供應商'的回應是一個嵌套物件:帶有 的頂級記錄 owner 子對象,a tags 字串數組,以及 scores 令人煩惱的是,根據字段混合整數和小數。手動鍵入結構意味著獲得 owner 築巢正確,標記每一個 snake_case 關鍵,並決定如何處理該混合數組。
我將樣本回應貼到轉換器中,以資源命名根類型,然後返回一個結構 Owner 作為內聯嵌套結構, Tags 作為 []string, 和 Scores 正確拓寬至 []float64. 的 id 字段出來了 ID 與a json:"id" 標籤,所以它既傳遞了行情,又解碼了真密鑰。我將其直接複製到客戶端包中,然後轉向邏輯,這就是我真正想花時間的地方。結構不是工作中有趣的部分,生成它意味著它不再是工作的任何部分。
我之所以在這些地方找到轉換器而不是手寫結構,並不是懶惰,而是機械部件,導出、標記和嵌套,正是我在思考邏輯時犯錯的部分。將它們卸載到確定性工具意味著結構在第一次編譯時是正確的,並且在第一次運行時解碼正確,這在嵌套有效負載上可以節省真正的調試會話。當我需要結構在被重新編碼後也能生存時,我會打開 omitempty 因此,零值不會出現在輸出中,標籤將顯示為 json:"key,omitempty" 為往返做好準備。
值得了解的限制是什麼?
一些誠實的邊緣。第一個是 null. JSON null 它本身不攜帶類型信息,因此是一個字段 null 在您的樣本中,鍵入為 interface{}. 工具無法推斷出任何內容;如果您知道真實類型,請在貼上後在編輯器中更改它,或向轉換器提供該欄位具有真實值的樣本,以便可以匯出該類型。這是資料的屬性,而不是工具的缺點。
第二個是數值精度,它是一般 JSON 解析的屬性,而不是專門這個轉換器的屬性。該工具使用瀏覽器解析您的 JSON' JSON 解析器,它將數字表示為雙精度浮點數,因此大約 2 到 53 次方的整數在解析時(在工具看到它們之前)會失去精確度。生成的 int64 場地夠寬 握住 一個大 ID,但如果該 ID 以這麼大的裸 JSON 數字形式到達,則解析已將其四捨五入。對於真正大的整數 ID,穩健的動作是在 JSON 中將它們作為字串攜帶,這可以保持它們精確並允許您將欄位鍵入為 string.
第三,推理是起點,而不是福音。該工具為您提供了樣本支援的類型,但只有您知道在此回應中恰好是整數的欄位實際上是可歸零計數,或者 a float64 應該是一個 json.Number 避免精度損失。將輸出視為您精煉的正確初稿,而不是刻在石頭上的合約。對於任何語言的每個 JSON 類型產生器都是如此。
最後,轉換器產生內聯嵌套結構,它將整個形狀保留在一個聲明中,您可以將其貼上為一個區塊。這是生成結構最常見、最可讀的風格,這就是 Go 生態系統中工具流行的內容。如果您寧願為深度重複使用的子物件提供單獨的命名類型,那麼一旦內聯版本進入編輯器,您就可以手動進行重構,通常是 IDE 的五秒摘錄。
常見問題
什麼是 JSON to Go 結構轉換器? JSON to Go 結構轉換器將 JSON 文件轉換為描述它的 Go 類型聲明。每個物件都成為一個結構,每個欄位都會得到一個 json:"鍵"標籤和值類型是推斷的,因此您可以使用編碼/json 解組相同的數據,而無需手動編寫結構。
如何將 JSON 轉換為 Go 結構? 將 JSON 貼到輸入框中,輸入 root 類型的名稱,選擇整數和標籤選項,然後按一下「轉換」。該工具使用 json 標籤列印 Go 結構定義,您可以將其直接複製到。go 檔案中。
為什麼 Go 欄位名稱與我的 JSON 金鑰不同? Go 僅對匯出的欄位進行編碼,因此每個欄位名稱都大寫,並且常見的首字母縮寫會變成大寫以匹配 golint。 json:"..."每個欄位上的標籤保留原始鍵,因此 json。Unmarshal 仍然正確映射數據,儘管重新命名了欄位。
JSON 數字如何對應到 Go 類型? 整數變為 int,如果啟用該選項,則變為 int64,小數點的數字變為 float64。當數組將整數和小數混合到相同位置時,類型會加寬為 float64,以便每個值都適合。
如何處理物件數組? 物件數組被合併到一個結構中,該結構包含任何元素所具有的每個鍵。如果兩個元素給出相同的鍵不相容類型,則該欄位將成為介面{},因此該結構仍然覆蓋整個數組。
空值會發生什麼變化? JSON null 本身不提供類型信息,因此該欄位被鍵入為 interface{}。如果您知道真實類型,請在貼上後在編輯器中更改它,或在 JSON 中提供非空範例值,以便推斷類型。
我的 json 上傳到任何地方了嗎? 不。轉換完全在您的瀏覽器中使用裝置上的 JavaScript 進行。您的 JSON 永遠不會上傳、記錄或存儲,並且一旦頁面加載,該工具就會繼續運行,並且網路會斷開連接。
JSON to Go 結構轉換器免費嗎? 是的。它是完全免費的,沒有註冊,沒有浮水印,也沒有使用上限。根據個人或商業專案的需要,將盡可能多的 JSON 文件轉換為 Go 結構。



