詳解golang中的結(jié)構(gòu)體編解碼神器Mapstructure庫
一:介紹
簡言之: mapstructure是GO字典(map[string]interface{})和Go結(jié)構(gòu)體之間轉(zhuǎn)換的編解碼工具。
核心方法:mapstructure.Decode(input interface{}, output interface{})
二:安裝
go get github.com/mitchellh/mapstructure
源碼地址:https://github.com/mitchellh/mapstructure
官方文檔地址:https://pkg.go.dev/github.com/mitchellh/mapstructure
三:使用
3.1: 簡單使用案例
案例:將一個JSON字符串解析為字典對象, 然后把字典綁定到一個結(jié)構(gòu)體對象中。
package main import ( "encoding/json" "fmt" "github.com/mitchellh/mapstructure" "log" ) type Person struct { Name string Age int Job string } func main() { // 定義一個JSON字符串 dataJson := `{ "name":"renshanwen", "age":18, "job": "engineer" }` // 將JOSN字符串解析成字典 var m map[string]interface{} err := json.Unmarshal([]byte(dataJson), &m) if err != nil { log.Fatal(err) } // 將結(jié)構(gòu)體m,綁定到結(jié)構(gòu)體對象p中 var p Person mapstructure.Decode(m, &p) fmt.Printf("name is %s, age is %d, job is %s.", p.Name, p.Age, p.Job) }
輸出結(jié)果:
name is renshanwen, age is 18, job is engineer.
3.2: 字段標(biāo)簽
字段標(biāo)簽作用:定義Go字典和GO結(jié)構(gòu)體字段映射關(guān)系。
默認(rèn):mapstructure使用結(jié)構(gòu)體中字段的名稱(大小寫不敏感)做這個映射,
案例:例如我們的結(jié)構(gòu)體有一個Name字段,mapstructure解碼時會在map[string]interface{}中查找鍵名name。
指定關(guān)系映射:
package main import ( "encoding/json" "fmt" "github.com/mitchellh/mapstructure" "log" ) type Person struct { Name string `mapstructure:"user_name"` Age int `mapstructure:"user_age"` Job string `mapstructure:"user_job"` } func main() { // 定義一個JSON字符串 dataJson := `{ "user_name":"renshanwen", "user_age":18, "user_job": "engineer" }` // 將JOSN字符串解析成結(jié)構(gòu)體 var m map[string]interface{} err := json.Unmarshal([]byte(dataJson), &m) if err != nil { log.Fatal(err) } // 將結(jié)構(gòu)體m,綁定到結(jié)構(gòu)體對象p中 var p Person mapstructure.Decode(m, &p) fmt.Printf("name is %s, age is %d, job is %s.", p.Name, p.Age, p.Job) }
3.3: 結(jié)構(gòu)體嵌套
如果入?yún)SON結(jié)構(gòu)比較復(fù)雜, 可以定義多重結(jié)構(gòu)體, mapstructure會自動幫助我們解析。
package main import ( "encoding/json" "fmt" "github.com/mitchellh/mapstructure" "log" ) type Person struct { Name string `mapstructure:"user_name"` Age int `mapstructure:"user_age"` Job string `mapstructure:"user_job"` } // Worker 結(jié)構(gòu)體嵌套 type Worker struct { Person Person Work string `mapstructure:"user_work"` } func main() { // 定義一個JSON字符串 dataJson := `{ "person":{ "user_name":"renshanwen", "user_age":18, "user_job":"engineer" }, "user_work":"code" }` // 將JOSN字符串解析成結(jié)構(gòu)體 var m map[string]interface{} err := json.Unmarshal([]byte(dataJson), &m) if err != nil { log.Fatal(err) } // 將結(jié)構(gòu)體m,綁定到結(jié)構(gòu)體對象w中 var w Worker mapstructure.Decode(m, &w) fmt.Printf("name is %s, age is %d, job is %s ,work is %s.", w.Person.Name, w.Person.Age, w.Person.Job, w.Work) }
3.4: 統(tǒng)一存儲未映射的值
可以定義一個字段,接收全部沒有映射的字段。
案例:
package main import ( "encoding/json" "fmt" "github.com/mitchellh/mapstructure" "log" ) type Person struct { Name string `mapstructure:"user_name"` Age int `mapstructure:"user_age"` Job string `mapstructure:"user_job"` } // Worker 結(jié)構(gòu)體嵌套 type Worker struct { Person Person Work string `mapstructure:"user_work"` Other map[string]interface{} `mapstructure:",remain"` // 未解析字段默認(rèn)分配到這里 } func main() { // 定義一個JSON字符串 dataJson := `{ "person":{ "user_name":"renshanwen", "user_age":18, "user_job":"engineer" }, "user_work":"code", "user_mather": "mather", "user_baby": "baby" }` // 將JOSN字符串解析成結(jié)構(gòu)體 var m map[string]interface{} err := json.Unmarshal([]byte(dataJson), &m) if err != nil { log.Fatal(err) } // 將結(jié)構(gòu)體m,綁定到結(jié)構(gòu)體對象w中 var w Worker mapstructure.Decode(m, &w) fmt.Printf("name is %s, age is %d, job is %s ,work is %s other is %s.", w.Person.Name, w.Person.Age, w.Person.Job, w.Work, w.Other) }
結(jié)果:
name is renshanwen, age is 18, job is engineer ,work is code other is map[user_baby:baby user_mather:mather].
3.5: 逆向轉(zhuǎn)換
結(jié)構(gòu)體—>字典
在反向解碼時,我們可以為某些字段設(shè)置mapstructure:“,omitempty”。這樣當(dāng)這些字段為默認(rèn)值時,就不會出現(xiàn)在結(jié)構(gòu)的map[string]interface{}。
package main import ( "encoding/json" "fmt" "github.com/mitchellh/mapstructure" ) type Person struct { Name string `mapstructure:"user_name"` Age int `mapstructure:"user_age"` Job string `mapstructure:"user_job,omitempty"` // ,omitempty表示如果結(jié)構(gòu)體對象沒有,則不會解析到字典中。 } // Worker 結(jié)構(gòu)體嵌套 type Worker struct { Person Person Work string `mapstructure:"user_work"` Other map[string]interface{} `mapstructure:",remain"` // 未解析字段默認(rèn)分配到這里 } func main() { // 定義一個JSON字符串 worker := &Worker{ Work: "code", } worker.Person.Name = "renshanwen" worker.Person.Age = 18 var m map[string]interface{} mapstructure.Decode(worker, &m) data, _ := json.Marshal(m) fmt.Println(string(data)) // {"Other":null,"Person":{"user_age":18,"user_name":"renshanwen"},"user_work":"code"} }
3.6: 收集綁定信息
可以使用mapstructure.Metadata, 存儲綁定信息情況。
Keys: 綁定成功的
Unused:沒有綁定上的
Unset:缺失的
package main import ( "fmt" "github.com/mitchellh/mapstructure" ) type Person struct { Name string `mapstructure:"user_name"` Age int `mapstructure:"user_age"` Job string `mapstructure:"user_job,omitempty"` // ,omitempty表示如果結(jié)構(gòu)體對象沒有,則不會解析到字典中。 } func main() { m := map[string]interface{}{ "user_name": "renshanwen", "age": 18, "job": "engineer", } var p Person var metadata mapstructure.Metadata mapstructure.DecodeMetadata(m, &p, &metadata) fmt.Printf("keys:%#v unused:%#v Unset:%#v \n", metadata.Keys, metadata.Unused, metadata.Unset) // keys:[]string{"user_name"} unused:[]string{"age", "job"} Unset:[]string{"user_age", "user_job"} }
以上就是詳解golang中的結(jié)構(gòu)體編解碼神器Mapstructure庫的詳細(xì)內(nèi)容,更多關(guān)于go Mapstructure的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Go語言創(chuàng)建WebSocket服務(wù)的實現(xiàn)示例
這篇文章主要介紹了使用Go語言創(chuàng)建WebSocket服務(wù)的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03執(zhí)行g(shù)o?vendor第三方包版本沖突問題解決
這篇文章主要為大家介紹了執(zhí)行g(shù)o?vendor時,第三方包go版本沖突問題的解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07