github地址:github.com/mitchellh/mapstructure
简介 该库的作用是用于将map转换为结构体,或者将结构体转换为map,该库还做了很多处理时的错误处理。
比如当你获取到json或者gob数据的时候,不知道其具体结构,只能先将其转换为map[string]interface{},然后可以用该库将map[string]interface{}转换为方便处理的struct。
tag的使用 不定义tag的时候,使用字段名,注意字段名大小写敏感。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 type User struct { Username string }func main () { var u User b := map [interface {}]interface {}{ "Username" : "Alice" , } if err := mapstructure.Decode(b, &u); err != nil { fmt.Println("decode Interface config failed" ) } else { fmt.Println(u) } }
定义tag的话,会使用定义的tag,默认会读mapstructure。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 type User struct { Username string `mapstructure:"byby"` }func main () { var u User b := map [interface {}]interface {}{ "byby" : "Alice" , } if err := mapstructure.Decode(b, &u); err != nil { fmt.Println("decode Interface config failed" ) } else { fmt.Println(u) } }
也可以自定义读什么tag而不是读默认的mapstructure tag。此时需要使用NewDecoder,指定TagName为自定义的tag,Result部分为目标解码对象。
Decode里传入待解码的值。
PS:多个tag之间直接用空格分割。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 type User struct { Username string `disco:"byby" mapstructure:"hihi"` }func main () var u User b := map [interface {}]interface {}{ "byby" : "Alice" , } decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{TagName: "disco" , Result: &u}) if err != nil { fmt.Println(err) } if decoder.Decode(b); err != nil { fmt.Println(err) } fmt.Println(u) }
指定结构体非嵌套 指定非嵌套结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 type Person struct { Name string }type Friend struct { Person Person }func main () { var u Friend b := map [string ]interface {}{ "person" : map [string ]interface {}{"name" : "alice" }, } if err := mapstructure.Decode(b, &u); err != nil { fmt.Println("decode Interface config failed" ) } else { fmt.Println(u) } }
如果想指定Persion为非嵌套的,则在Person后面加上 mapstructure:",squash"
,此时输入不需要person的那层了,此时mapstructure看到squash标识,会将输入转化到Person struct里。
运行结果为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 type Person struct { Name string }type Friend struct { Person `mapstructure:",squash"` }func main () { var u Friend b := map [string ]interface {}{ "name" : "alice" , } if err := mapstructure.Decode(b, &u); err != nil { fmt.Println("decode Interface config failed" ) } else { fmt.Println(u) } }
如果传入
1 2 3 map [string ]interface {}{ "person" : map [string ]interface {}{"name" : "alice" }, }
则无法decode成功。
获取struct没有定义的字段 如果传入的map有某个字段,而struct没有定义这个字段,则默认情况下会忽略这个字段。
可以加上remain标识,接收一些struct没有定义的字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 type Friend struct { Name string Other map [string ]interface {} `mapstructure:",remain"` }func main () { var u Friend b := map [string ]interface {}{ "name" : "bob" , "address" : "123 Maple St." , } if err := mapstructure.Decode(b, &u); err != nil { fmt.Println("decode Interface config failed" ) } else { fmt.Println(u) } }
其他 忽略struct的字段,定义 `mapstructure:”,omitempty”``
WeakDecode WeakDecode允许能够最大兼容性的保证Decode的成功,比如传过来的是bool,使用的时候要改成int,比如有的数据库没有bool类型,只能用int表示,此时需要考虑使用WeakDecode。
WeakDecode用法示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 func main () { type Person struct { Name string Age int Emails []string OK int Bad int } input := map [string ]interface {}{ "name" : 123 , "age" : "42" , "emails" : map [string ]interface {}{}, "ok" : true , "bad" : false , } var result Person if err := mapstructure.WeakDecode(input, &result); err != nil { fmt.Println("......err......" , err) return } fmt.Println("........result......" , result) }
逆向转换 一般都是将map转换为struct,逆向转换就是将struct转换为map,转换的方法和map转struct类似。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 type Person struct { Name string Age int Emails []string OK int Bad int }func main () { p := &Person{ Name: "dj" , Age: 18 , } var m map [string ]interface {} mapstructure.Decode(p, &m) data, _ := json.Marshal(m) fmt.Println(string (data)) }
参考