- go数据结构与json数据结构对应( json.Unmarshal帮助手册)
bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON nul
注: 手册里可以看到转json时, 常见选项的含义和例子.
- 一些例子
go by example: json
package main
import (
"encoding/json"
"fmt"
"os"
)
type response1 struct {
Page int
Fruits []string
}
type response2 struct {
Page int `json:"page"`
Fruits []string `json:"fruits"`
}
func main() {
bolB, _ := json.Marshal(true)
fmt.Println(string(bolB))
intB, _ := json.Marshal(1)
fmt.Println(string(intB))
fltB, _ := json.Marshal(2.34)
fmt.Println(string(fltB))
strB, _ := json.Marshal("gopher")
fmt.Println(string(strB))
slcD := []string{"apple", "peach", "pear"}
slcB, _ := json.Marshal(slcD)
fmt.Println(string(slcB))
mapD := map[string]int{"apple": 5, "lettuce": 7}
mapB, _ := json.Marshal(mapD)
fmt.Println(string(mapB))
res1D := &response1{
Page: 1,
Fruits: []string{"apple", "peach", "pear"}}
res1B, _ := json.Marshal(res1D)
fmt.Println(string(res1B))
res2D := &response2{
Page: 1,
Fruits: []string{"apple", "peach", "pear"}}
res2B, _ := json.Marshal(res2D)
fmt.Println(string(res2B))
byt := []byte(`{"num":6.13,"strs":["a","b"]}`)
var dat map[string]interface{}
if err := json.Unmarshal(byt, &dat); err != nil {
panic(err)
}
fmt.Println(dat)
num := dat["num"].(float64)
fmt.Println(num)
strs := dat["strs"].([]interface{})
str1 := strs[0].(string)
fmt.Println(str1)
str := `{"page": 1, "fruits": ["apple", "peach"]}`
res := response2{}
json.Unmarshal([]byte(str), &res)
fmt.Println(res)
fmt.Println(res.Fruits[0])
//上面unmarshal得到的都是字节数组, 这里直接将字节数组写入流
enc := json.NewEncoder(os.Stdout)
d := map[string]int{"apple": 5, "lettuce": 7}
enc.Encode(d)
}
- go数据类型转json: struct tag for json: 结构体转json时作用
/*
Examples of struct field tags and their meanings:
// Field appears in JSON as key "myName".
Field int `json:"myName"`
// Field appears in JSON as key "myName" and
// the field is omitted from the object if its value is empty,
// as defined above.
Field int `json:"myName,omitempty"`
// Field appears in JSON as key "Field" (the default), but
// the field is skipped if empty.
// Note the leading comma.
Field int `json:",omitempty"`
// Field is ignored by this package.
Field int `json:"-"`
// Field appears in JSON as key "-".
Field int `json:"-,"
*/
- 默认
type user struct {
Name string
Age int
}
func main() {
u := user{
Name: "m1",
Age: 22,
}
b, _ := json.Marshal(u)
fmt.Println(string(b))
}
// {"Name":"m1","Age":22}
- json tag:
type user struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
u := user{
Name: "m1",
Age: 22,
}
b, _ := json.Marshal(u)
fmt.Println(string(b))
}
// {"name":"m1","age":22}
- struct实例缺少字段
type user struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
u := user{
Name: "m1",
}
b, _ := json.Marshal(u)
fmt.Println(string(b))
}
// {"name":"m1","age":0}
- josn tag: omitempty
//例子1:
type user struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
}
func main() {
u := user{
Name: "m1",
Age: 10,
}
b, _ := json.Marshal(u)
fmt.Println(string(b))
}
//{"name":"m1","age":10}
//例子2:
type user struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
}
func main() {
u := user{
Name: "m1",
Age: 0,
}
b, _ := json.Marshal(u)
fmt.Println(string(b))
}
//{"name":"m1"}
//例子3:
type user struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
}
func main() {
u := user{
Name: "m1",
}
b, _ := json.Marshal(u)
fmt.Println(string(b))
}
//{"name":"m1"}
- 删除字段:
//例子1:
type user struct {
Name string `json:"name"`
Age int `json:"-"`
}
func main() {
u := user{
Name: "m1",
Age: 12,
}
b, _ := json.Marshal(u)
fmt.Println(string(b))
}
//{"name":"m1"}
//例子2:
type user struct {
Name string `json:"name"`
Age int `json:"-"`
}
func main() {
u := user{
Name: "m1",
Age: 0,
}
b, _ := json.Marshal(u)
fmt.Println(string(b))
}
//{"name":"m1"}
- json tag: string
// 例1:
type user struct {
Name string `json:"name"`
Age int `json:",string"`
}
func main() {
u := user{
Name: "m1",
Age: 22,
}
b, _ := json.Marshal(u)
fmt.Println(string(b))
}
//{"name":"m1","Age":"22"}
// 例2:
type user struct {
Name string `json:"name",int"` //str转int, 出错,但不报错
Age int
}
func main() {
u := user{
Name: "m1",
Age: 22,
}
b, err := json.Marshal(u)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(b))
}
//{"name":"m1","Age":"22"}
- 转go数据结构
- json类型和struct不匹配: 转换失败, 报错(支持类型校验)
type user struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
var jsonStr = `
{
"name":"m1",
"age":"22"
}
`
var u user
err := json.Unmarshal([]byte(jsonStr), &u)
if err != nil {
fmt.Println(err)
}
fmt.Println(u)
}
//json: cannot unmarshal string into Go struct field user.age of type int
//{m1 0}
- 支持类型转换(但不支持自适应)
type user struct {
Name string `json:"name"`
Age int `json:"age,string"`
}
func main() {
var jsonStr = `
{
"name":"m1",
"age":"22"
}
`
var u user
err := json.Unmarshal([]byte(jsonStr), &u)
if err != nil {
fmt.Println(err.Error())
}
fmt.Printf("%#v",u)
}
//main.user{Name:"m1", Age:22}
- 不支持弱类型转换
type user struct {
Name string `json:"name"`
Age int `json:"age,string"`
}
func main() {
var jsonStr = `
{
"name":"m1",
"age":22
}
`
var u user
err := json.Unmarshal([]byte(jsonStr), &u)
if err != nil {
fmt.Println(err.Error())
}
fmt.Printf("%#v",u)
}
//json: invalid use of ,string struct tag, trying to unmarshal unquoted value into
// int
//main.user{Name:"m1", Age:0}
- 如果json缺字段, struct以零值填充
type user struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
var jsonStr = `
{
"name":"m1"
}
`
var u user
err := json.Unmarshal([]byte(jsonStr), &u)
if err != nil {
fmt.Println(err)
}
fmt.Println(u)
}
//{m1 0}
- 无论多少层的json 都能Unmarshal到 map[string]interface{}中
const jsonStr = `
{
"name":{
"first":"Janet",
"last":"Prichard",
"address":{"age":22}
},
"age":47
}
`
func main() {
m := map[string]interface{}{}
json.Unmarshal([]byte(jsonStr), &m)
fmt.Printf("%#v", m)
}
//map[string]interface {}{"age":47, "name":map[string]interface {}{"address":map[string]interface {}{"age":22}, "first":"Janet", "last":"Prichard"}}
临时忽略struct空字段
临时添加额外的字段
临时粘合两个struct
一个json切分成两个struct
临时改名struct的字段
用字符串传递数字
容忍字符串和数字互转
容忍空数组作为对象
使用 MarshalJSON支持time.Time
使用 RegisterTypeEncoder支持time.Time
使用 MarshalText支持非字符串作为key的map
使用 json.RawMessage
使用 json.Number
统一更改字段的命名风格
使用私有的字段
忽略掉一些字段
忽略掉一些字段2
- 练习: 写出下列json的struct:
{
"resultcode": "200",
"reason": "Return Successd!",
"result": {
"province": "浙江",
"city": "杭州",
"areacode": "0571",
"zip": "310000",
"company": "中国移动",
"card": ""
}
}
type Province struct {
Resultcode string `json:"resultcode"`
Reason string `json:"reason"`
Results Results `json:"results"`
}
type Results struct {
Province string `json:"province"`
City string `json:"city"`
Areacode string `json:"areacode"`
Zip string `json:"zip"`
Company string `json:"company"`
Card string `json:"card"`
}
- 支持tag
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 := Decode(input, &result)
if err != nil {
panic(err)
}
fmt.Printf("%#v", result)
//Output:
//
//mapstructure.Person{Name:"Mitchell", Age:91}
}
- 支持字段类型校验
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 := Decode(input, &result)
if err == nil {
panic("should have an error")
}
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\'
}
- 支持结构体嵌套
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 := Decode(input, &result)
if err != nil {
panic(err)
}
fmt.Printf("%s %s, %s", result.FirstName, result.LastName, result.City)
//Output:
//
//Mitchell Hashimoto, San Francisco
}
- 支持类型自适应(week转换)
- 实际的用处
// json数据: data对应结构体可能不同, 所以定义为 []map[string]string
{
"type": "UPDATE",
"database": "blog",
"table": "blog",
"data": [
{
"blogId": "100001",
"title": "title",
"content": "this is a blog",
"uid": "1000012",
"state": "1"
}
]
}
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"
}
]}`)
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)
}
}
参考: GO小知识之实例演示 json 如何转化为 map 和 struct
1. json.Unmarshal 将JSON转为 map[string]interface{}。
缺陷:
需要检查key是否存在
key 容易写错
2. 改进: 将不固定的部分即: Data: []map[string]string
固定的部分保持
3. 将可变字段用mapstructure转换为struct, 能自适应value类型
- 取值
package main
import "github.com/tidwall/gjson"
const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
func main() {
value := gjson.Get(json, "name.last")
println(value.String())
}
- 遍历
const json = `
{
"name":{
"first":"Janet",
"last":"Prichard",
"address":{"age":22}
},
"age":47
}
`
func main() {
result := gjson.Get(json, "name")
result.ForEach(func(key, value gjson.Result) bool {
println(value.String())
return true // keep iterating
})
}
- Unmarshal to a map
m, ok := gjson.Parse(json).Value().(map[string]interface{})
if !ok {
// not a map
}