使用第三方包 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