go语言 map转成struct结构

Golang piniu 1337浏览 0评论

使用第三方包 mapstructure 处理json转struct

git地址:

  • https://github.com/goinggo/mapstructure

安装 mapstructure

go get github.com/goinggo/mapstructure

DEMO

以下代码中,定义结构体时,tag参数需要用反引号,因在页面中反引号被解析了,所以看不到,但使用时一定要用反引号包括

1.支持tag

package main

import (
	"fmt"
	"github.com/mitchellh/mapstructure"
)

func main() {
    // Note that the mapstructure tags defined in the struct type
    // can indicate which fields the values are mapped to.
    type Person struct {
        Name string `mapstructure:"person_name"`
        Age  int    `mapstructure:"person_age"`
    }

    input := map[string]interface{}{
        "person_name": "Mitchell",
        "person_age":  91,
    }

    var result Person
    err := mapstructure.Decode(input, &result)
    if err != nil {
        panic(err)
    }

    fmt.Printf("%#v", result)
    
    //Output:
    //
    //mapstructure.Person{Name:"Mitchell", Age:91}
}

2.支持字段类型校验

package main

import (
	"fmt"
	"github.com/mitchellh/mapstructure"
)

func main() {
    type Person struct {
        Name   string
        Age    int
        Emails []string
        Extra  map[string]string
    }

    // This input can come from anywhere, but typically comes from
    // something like decoding JSON where we're not quite sure of the
    // struct initially.
    input := map[string]interface{}{
        "name":   123,
        "age":    "bad value",
        "emails": []int{1, 2, 3},
    }

    var result Person
    err := mapstructure.Decode(input, &result)
    if err == nil {
        fmt.Println(result)
    } else {
        fmt.Println(err.Error())
    }

    //Output:
    //
    //5 error(s) decoding:
    //* 'Age' expected type 'int', got unconvertible type 'string'
    //* 'Emails[0]' expected type 'string', got unconvertible type 'int'
    //* 'Emails[1]' expected type 'string', got unconvertible type 'int'
    //* 'Emails[2]' expected type 'string', got unconvertible type 'int'
    //* 'Name' expected type 'string', got unconvertible type 'int'
}

3.支持结构体嵌套

package main

import (
	"fmt"
	"github.com/mitchellh/mapstructure"
)

func main() {
    // Squashing multiple embedded structs is allowed using the squash tag.
    // This is demonstrated by creating a composite struct of multiple types
    // and decoding into it. In this case, a person can carry with it both
    // a Family and a Location, as well as their own FirstName.
    type Family struct {
        LastName string
    }
    type Location struct {
        City string
    }
    type Person struct {
        Family    `mapstructure:",squash"`
        Location  `mapstructure:",squash"`
        FirstName string
    }

    input := map[string]interface{}{
        "FirstName": "Mitchell",
        "LastName":  "Hashimoto",
        "City":      "San Francisco",
    }

    var result Person
    err := mapstructure.Decode(input, &result)
    if err != nil {
        panic(err)
    }

    fmt.Printf("%s %s, %s", result.FirstName, result.LastName, result.City)
    
    //Output:
    //
    //Mitchell Hashimoto, San Francisco
}

4. 支持类型自适应(week转换)

package main

import (
	"encoding/json"
	"fmt"
	"github.com/mitchellh/mapstructure"
)

type Event struct {
    Type     string              `json:"type"`
    Database string              `json:"database"`
    Table    string              `json:"table"`
    Data     []map[string]string `json:"data"`
}

type Blog struct {
    BlogId  string `mapstructure:"blogId"`
    Title   string `mapstructrue:"title"`
    Content string `mapstructure:"content"`
    Uid     int32  `mapstructure:"uid"`
    State   int32  `mapstructure:"state"`
}

func main() {
    msg := []byte(`{
    "type": "UPDATE",
    "database": "blog",
    "table": "blog",
    "data": [
        {
            "blogId": "100001",
            "title": "title",
            "content": "this is a blog",
            "uid": "1000012",
            "state": "1"
		},
		{
            "blogId": "100002",
            "title": "title2",
            "content": "this is a news",
            "uid": "2000011",
            "state": "0"
		}
    ]}`)
    e := Event{}
    if err := json.Unmarshal(msg, &e); err != nil {
        panic(err)
    }
    if e.Table == "blog" {
        var blogs []Blog
        if err := mapstructure.WeakDecode(e.Data, &blogs); err != nil {
            panic(err)
        }

        fmt.Println(blogs)

        for _, b := range blogs {
		fmt.Println(b)
		fmt.Printf("%v, %s, %s, %v, %v\n", b.BlogId, b.Title, b.Content, b.Uid, b.State)
	}
    }
}

//Output:
//
//[{100001 title this is a blog 1000012 1} {100002 title2 this is a news 2000011 0}]
//
//{100001 title this is a blog 1000012 1}
//100001, title, this is a blog, 1000012, 1
//
//{100002 title2 this is a news 2000011 0}
//100002, title2, this is a news, 2000011, 0


发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • * 昵称:
  • * 邮箱: