Go的json解析:Marshal與Unmarshal

Json Marshal:將數據編碼成json字符串

看一個簡單的例子

type Stu struct {
    Name  string `json:"name"`
    Age   int
    HIgh  bool
    sex   string
    Class *Class `json:"class"`
}

type Class struct {
    Name  string
    Grade int
}

func main() {
    //實例化一個數據結構,用於生成json字符串
    stu := Stu{
        Name: "張三",
        Age:  18,
        HIgh: true,
        sex:  "男",
    }

    //指針變量
    cla := new(Class)
    cla.Name = "1班"
    cla.Grade = 3
    stu.Class=cla

    //Marshal失敗時err!=nil
    jsonStu, err := json.Marshal(stu)
    if err != nil {
        fmt.Println("生成json字符串錯誤")
    }

    //jsonStu是[]byte類型,轉化成string類型便於查看
    fmt.Println(string(jsonStu))
}

結果:

{"name":"張三","Age":18,"HIgh":true,"class":{"Name":"1班","Grade":3}}

從結果中可以看出:

  • 只要是可導出成員(變量首字母大寫),都可以轉成json。因成員變量sex是不可導出的,故無法轉成json。
  • 如果變量打上了json標籤,如Name旁邊的 json:"name" ,那麼轉化成的json key就用該標籤“name”,否則取變量名作爲key,如“Age”,“HIgh”。
  • bool類型也是可以直接轉換爲json的value值。Channel, complex 以及函數不能被編碼json字符串。當然,循環的數據結構也不行,它會導致marshal陷入死循環。
  • 指針變量,編碼時自動轉換爲它所指向的值,如cla變量。 (當然,不傳指針,Stu struct的成員Class如果換成Class struct類型,效果也是一模一樣的。只不過指針更快,且能節省內存空間。)
  • 最後,強調一句:json編碼成字符串後就是純粹的字符串了。

上面的成員變量都是已知的類型,只能接收指定的類型,比如string類型的Name只能賦值string類型的數據。 但有時爲了通用性,或使代碼簡潔,我們希望有一種類型可以接受各種類型的數據,並進行json編碼。這就用到了interface{}類型。

Json Unmarshal:將json字符串解碼到相應的數據結構

我們將上面的例子進行解碼

type StuRead struct {
    Name  interface{} `json:"name"`
    Age   interface{}
    HIgh  interface{}
    sex   interface{}
    Class interface{} `json:"class"`
    Test  interface{}
}

type Class struct {
    Name  string
    Grade int
}

func main() {
    //json字符中的"引號,需用\進行轉義,否則編譯出錯
    //json字符串沿用上面的結果,但對key進行了大小的修改,並添加了sex數據
    data:="{\"name\":\"張三\",\"Age\":18,\"high\":true,\"sex\":\"男\",\"CLASS\":{\"naME\":\"1班\",\"GradE\":3}}"
    str:=[]byte(data)

    //1.Unmarshal的第一個參數是json字符串,第二個參數是接受json解析的數據結構。
    //第二個參數必須是指針,否則無法接收解析的數據,如stu仍爲空對象StuRead{}
    //2.可以直接stu:=new(StuRead),此時的stu自身就是指針
    stu:=StuRead{}
    err:=json.Unmarshal(str,&stu)

    //解析失敗會報錯,如json字符串格式不對,缺"號,缺}等。
    if err!=nil{
        fmt.Println(err)
    }

    fmt.Println(stu)
}

結果:

{張三 18 true <nil> map[naME:1班 GradE:3] <nil>}

總結:

  • json字符串解析時,需要一個“接收體”接受解析後的數據,且Unmarshal時接收體必須傳遞指針。否則解析雖不報錯,但數據無法賦值到接受體中。如這裏用的是StuRead{}接收。
  • 解析時,接收體可自行定義。json串中的key自動在接收體中尋找匹配的項進行賦值。匹配規則是: (1) 先查找與key一樣的json標籤,找到則賦值給該標籤對應的變量(如Name)。 (2) 沒有json標籤的,就從上往下依次查找變量名與key一樣的變量,如Age。或者變量名忽略大小寫後與key一樣的變量。如HIgh,Class。第一個匹配的就賦值,後面就算有匹配的也忽略。 (前提是該變量必需是可導出的,即首字母大寫)。
  • 不可導出的變量無法被解析(如sex變量,雖然json串中有key爲sex的k-v,解析後其值仍爲nil,即空值)
  • 當接收體中存在json串中匹配不了的項時,解析會自動忽略該項,該項仍保留原值。如變量Test,保留空值nil。 

轉自:https://cloud.tencent.com/developer/article/1515861 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章