输出:
value: main.Person{Name:"Tim", Age:31, Gender:""}, keys: []string{"Name", "Age"}, Unused keys: []string{"email"}, Unset keys: []string{"Gender"}从这个例子我们可以看出,使用 Metadata 可以记录我们结构体以及 map[string]interface{} 的差异,相同的部分会正确映射到对应的字段中,而差异则使用了 Unused 和 Unset 来表达 。
- Unused:map 中有着结构体所没有的字段 。
- Unset:结构体中有着 map 中所没有的字段 。
func omitemptyDecode() { // 添加 omitempty 注释以避免空值的映射键 type Family struct {LastName string } type Location struct {City string } type Person struct {*Family`mapstructure:",omitempty"`*Location `mapstructure:",omitempty"`AgeintFirstName string } result := &map[string]interface{}{} input := Person{FirstName: "Somebody"} err := mapstructure.Decode(input, &result) if err != nil {panic(err) } fmt.Printf("%+vn", result)}输出:&map[Age:0 FirstName:Somebody]这里我们可以看到 *Family 和 *Location 都被设置了 omitempty,所以在解析过程中会忽略掉空值 。而 Age 没有设置,并且 input 中没有对应的 value,所以在解析中使用对应类型的零值来表达,而 int 类型的零值就是 0 。剩余字段
func remainDataDecode() { type Person struct {NamestringAgeintOther map[string]interface{} `mapstructure:",remain"` } input := map[string]interface{}{"name":"Tim","age":31,"email":"one@gmail.com","gender": "male", } var result Person err := mapstructure.Decode(input, &result) if err != nil {panic(err) } fmt.Printf("%#vn", result)}输出:main.Person{Name:"Tim", Age:31, Other:map[string]interface {}{"email":"one@gmail.com", "gender":"male"}}从代码可以看到 Other 字段被设置了 remain,这意味着 input 中没有正确映射的字段都会被放到 Other 中 , 从输出可以看到 , email 和 gender 已经被正确的放到 Other 中了 。自定义标签
func tagDecode() { // 请注意,结构类型中定义的 mapstructure 标签可以指示将值映射到哪些字段 。type Person struct {Name string `mapstructure:"person_name"`Ageint`mapstructure:"person_age"` } input := map[string]interface{}{"person_name": "Tim","person_age":31, } var result Person err := mapstructure.Decode(input, &result) if err != nil {panic(err) } fmt.Printf("%#vn", result)}输出:main.Person{Name:"Tim", Age:31}在 Person 结构中,我们将 person_name 和 person_age 分别映射到 Name 和 Age 中,从而达到在不破坏结构的基础上,去正确的解析 。弱类型解析正如前面所说,mapstructure 提供了类似 PHP 解析弱类型结构的方法 。
func weaklyTypedInputDecode() { type Person struct {NamestringAgeintEmails []string } // 此输入可以来自任何地方,但通常来自诸如解码 JSON 之类的东西,由 PHP 等弱类型语言生成 。input := map[string]interface{}{"name":123,// number => string"age":"31", // string => number"emails": map[string]interface{}{}, // empty map => empty array } var result Person config := &mapstructure.DecoderConfig{WeaklyTypedInput: true,Result:&result, } decoder, err := mapstructure.NewDecoder(config) if err != nil {panic(err) } err = decoder.Decode(input) if err != nil {panic(err) } fmt.Printf("%#vn", result)}输出:main.Person{Name:"123", Age:31, Emails:[]string{}}从代码可以看到,input 中的 name、age 和 Person 结构体中的 Name、Age 类型不一致,而 email 更是离谱,一个字符串数组,一个是 map 。但是我们通过自定义 DecoderConfig,将 WeaklyTypedInput 设置成 true 之后,mapstructure 很容易帮助我们解决这类弱类型的解析问题 。
但是也不是所有问题都能解决,通过源码我们可以知道有如下限制:
//- bools to string (true = "1", false = "0")//- numbers to string (base 10)//- bools to int/uint (true = 1, false = 0)//- strings to int/uint (base implied by prefix)//- int to bool (true if value != 0)//- string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F,//FALSE, false, False. Anything else is an error)//- empty array = empty map and vice versa//- negative numbers to overflowed uint values (base 10)//- slice of maps to a merged map//- single values are converted to slices if required. Each//element is weakly decoded. For example: "4" can become []int{4}//if the target type is an int slice.
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 一文教你学会使用Nginx
- Go 语言为什么建议多使用切片,少使用数组?
- Java垃圾回收器的工作原理及监视不再使用对象的机制
- C++中new与malloc:内存分配机制深度解析
- 独立服务器是什么?基础知识与工作原理解析
- 酷路泽四驱怎么使用
- Go 语言使用 Echo 构建高性能 Web 应用
- Python Selenium实现自动化测试及Chrome驱动使用!
- C++中使用宏定义一个函数:灵活性与风险并存
- 作为 .NET 开发人员,我为什么开始使用 Python?
