Go 語言神奇的 JSON

今天我想和你們分享 Go 語言一些很是實用的技巧,用於編碼和解碼 JSON 文檔。Go 語言的 encoding/json 包有一些有趣的特性,幫助咱們輕鬆地解析 JSON 文檔。你能夠輕鬆地將大多數實際應用中的 JSON 轉換爲帶有 Go 語言結構體標籤的接口或者是 Marshaler 和 Unmarshaler 接口。golang

但有一個案例比較棘手:包含轉義 JSON 元素的 JSON 文檔。以下所示:json

{
   "id": 12345,
   "name": "Test Document",
   "payload": "{\"message\":\"hello!\"}"
}

我不建議構建像這樣建立文檔的應用程序,但有時候這樣的狀況是難以免的,你但願像日常的 JSON 那樣,一步就能解析這個文檔。也許你從以下兩種類型開始:ide

type LogEntry struct {
   ID      int    `json:"id"`
   Name    string `json:"name"`
   Payload string `json:"payload"`
}
type LogPayload struct {
   Message string `json:"message"`
}

Matt Holt 的 json-to-go 可以幫助你從 JSON 示例中生成初始結構體,不妨試一下!ui

首先要將 LogEntry.Payload 的類型從 string 類型改成 LogPayload 類型。這點很重要,由於這是你最終想要獲得的,這就是 encoding/json 包處理該元素的方式。如今的問題是 payload 元素的實際入站類型是一個 JSON 字符串。你須要在 LogPayload 類型上實現 Unmarshaler 接口,並將其解碼爲字符串,而後再解碼爲 LogPayload 類型。編碼

func (lp *LogPayload) UnmarshalJSON(b []byte) error {
   var s string
   if err := json.Unmarshal(b, &s); err != nil {
       return err
   }
   if err := json.Unmarshal([]byte(s), lp); err != nil {
       return err
   }

   return nil
}

看起來很棒,然而不幸的是第二個 json.Unmarshal 調用將會致使調用堆棧的遞歸。你須要將它解碼成一箇中間類型,你能夠經過定義一個帶有 LogPayload 基礎類型的新類型來實現,例如這樣:code

type fauxLogPayload LogPayload

你能夠將上面的代碼調整一下,將其解碼爲 fauxLogPayload 類型,而後將結果轉換爲 LogPayload 類型。遞歸

func (lp *LogPayload) UnmarshalJSON(b []byte) error {
   var s string
   if err := json.Unmarshal(b, &s); err != nil {
       return err
   }
   var f fauxLogPayload
   if err := json.Unmarshal([]byte(s), &f); err != nil {
       return err
   }

   *lp = LogPayload(f)

   return nil
}

如今,要解析整個文檔的調用站點變得更好了,也簡潔了:接口

func main() {
   doc := []byte(`{
       "id": 12345,
       "name": "Test Document",
       "payload": "{\"message\":\"test\"}"
   }`)
   var entry LogEntry
   if err := json.Unmarshal(doc, &entry); err != nil {
       fmt.Println("Error!", err)
   }
   fmt.Printf("%v", entry)
}

你能夠在 Go Playground 找到這些代碼。文檔

我但願這個例子說明了 Go 語言能夠多麼容易地將對 encoding/decoding 的關注點從業務邏輯中分離出來。你能夠在任什麼時候候使用此方法將基本 JSON 類型轉換爲更復雜的用戶定義類型。字符串

Cheers!

感謝 Redditors BubuX 和 quiI ,他們建議連接到 JSON -to- Go ,並在 main.go 中爲個人 JSON 使用 Go 語言的字符串文字。

原文連接: https://medium.com/@turgon/json-in-go-is-magical-c5b71505a937
譯文連接:https://studygolang.com/articles/12619做者:turgon 譯者:SergeyChang 校對:rxcai

相關文章
相關標籤/搜索