首頁 > 軟體

詳解Go語言中結構體與JSON間的轉換

2022-12-15 14:02:31

前言

在日常開發中,我們往往會將 JSON 解析成對應的結構體,反之也會將結構體轉成 JSON。接下來本文會通過 JSON 包的兩個函數,來介紹 JSON 與結構體之間的轉換。

結構體轉 JSON

Marshal(v any) ([]byte, error):將 v 轉成 JSON 資料,以 []byte 的形式返回。

import (
    "encoding/json"
    "fmt"
)

type User struct {
    Name           string
    Age            int
    Height         float64
    Weight         *float64
    Child          bool
    marriageStatus string
}

func main() {
    weight := 120.5
    user := User{
        Name:           "gopher",
        Age:            18,
        Height:         180.5,
        Weight:         &weight,
        Child:          false,
        marriageStatus: "未婚",
    }
    jsonBytes, err := json.Marshal(user)
    if err != nil {
        fmt.Println("error: ", err)
        return
    }
    fmt.Println(string(jsonBytes)) // {"Name":"gopher","Age":18,"Height":180.5,"Weight":120.5,"Child":false}
}

執行結果:

{"Name":"gopher","Age":18,"Height":180.5,"Weight":120.5,"Child":false}

根據結果可知:

  • 不可匯出欄位(欄位名以小寫字母開頭),是不能被轉成 JSONkey 的,這也符合 Go 的語法規定,以小寫字母開頭的變數或結構體欄位等,不能在包外被存取。
  • 轉換後的欄位名,與結構體欄位的名字一樣。
  • 如果欄位是指標型別,轉換後的值為指標指向的欄位值。

如果我們想要指定欄位轉換之後的命名,或者將一個可匯出的欄位進行忽略,可以通過給結構體欄位打上 JSON 標籤的方式實現。

import (
    "encoding/json"
    "fmt"
)

type User struct {
    Name           string   `json:"name"`
    Age            int      `json:"age"`
    Height         float64  `json:"height"`
    Weight         *float64 `json:"weight"`
    Child          bool     `json:"child"`
    MarriageStatus string   `json:"-"`
}

func main() {
    weight := 120.5
    user := User{
        Name:           "gopher",
        Age:            18,
        Height:         180.5,
        Weight:         &weight,
        Child:          false,
        MarriageStatus: "未婚",
    }
    jsonBytes, err := json.Marshal(user)
    if err != nil {
        fmt.Println("error: ", err)
        return
    }
    fmt.Println(string(jsonBytes)) // {"name":"gopher","age":18,"height":180.5,"weight":120.5,"child":false}
}

通過給結構體欄位定打上 JSON 標籤,可指定轉成 JSON 後的欄位名,如果 JSON 標籤的值為 -,則在轉換 JSON 時忽略此欄位。

JSON 解析結構體

Unmarshal(data []byte, v any) error:將 JSON 解析成指定的結構體。

import (
    "encoding/json"
    "fmt"
)

type User struct {
    Name           string  `json:"name"`
    Age            int     `json:"age"`
    Height         float64 `json:"height"`
    Child          bool    `json:"-"`
    marriageStatus string
}

func main() {
    userStr := `
    {
      "name": "gopher",
      "age": 18,
      "height": 180.5,
      "child": true,
      "marriageStatus": "未婚"
    }
    `
    user := &User{}
    err := json.Unmarshal([]byte(userStr), &user)
    if err != nil {
        fmt.Println("error: ", err)
        return
    }
    fmt.Printf("%#v", user) // &main.User{Name:"gopher", Age:18, Height:180.5, Child:false, marriageStatus:""}
}

執行結果:

&main.User{Name:"gopher", Age:18, Height:180.5, Child:false, marriageStatus:""}

根據結果可知:

使用Unmarshal函數時,我們需要傳入結構體的指標型別,否則結構體欄位的值將不會被改變,因為底層是通過指標去修改結構體欄位的值。

JSON 解析時,JSONkey 與結構體欄位的匹配規則是:

  • 優先查詢 JSON 標籤值和 key 一樣的,找到則將 value 賦值給對應欄位。
  • 如果沒有 JSON 標籤值與 key 相匹配,則根據欄位名進行匹配。

可以發現,如果結構體欄位是非匯出欄位或 JSON 標籤的值為 -,將不會被匹配到。

小結

本文介紹了 Go 語言裡,JSON 與結構體之間的轉換。在結構體轉 JSON 時,我們可以通過給欄位打標籤,指定轉換後的 key 命名,需要注意的是,如果結構體的欄位為非匯出欄位或欄位的 JSON 標籤值為 -,在轉換 JSON 時,將會被忽略。反之 JSON 解析結構體時也是一樣的。

到此這篇關於詳解Go語言中結構體與JSON間的轉換的文章就介紹到這了,更多相關Go語言結構體 JSON內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com