json不用多说,一种跨语言的交换协议,这里探讨一下Go语言对json的支持。
Go对于json有官方自己的解析包,先谈一下json的解码方式。解码的api如下:
func Unmarshal (data []byte, v interface{})
在go中,json解码的数据结构有两种,一种是解析到结构体,一种是解析到空的interface。
以数据 {"changes": [{"index":5, "armid":6},{"index":9,"armid":10}]} 为例
1,解析到结构体
package main import ( "encoding/json" "fmt" ) func main() { type change struct { Index int Armid int } type change_slice struct { Changes []change } var msg change_slice str := `{"changes": [{"armid":3,"Index":5}, {"armid":3,"Index":6}]}` err := json.Unmarshal([]byte(str), &msg) if err!=nil { fmt.Println("Can't decode json message",err) } fmt.Println(msg) for _, change := range msg.Changes { fmt.Println(change.Armid, change.Index) } }
运行结果是:
{[{5 3} {6 3}]} 3 5 3 6
需要注意的是:
(1)解析到结构体时只能解析到结构体中的首字母大写的变量
(2)结构体中数值对应json中的key是大小写不敏感的
2,解析到interface
package main import ( "encoding/json" "fmt" ) func main() { str := `{"changes": [{"armid":3,"Index":5}, {"armid":3,"Index":6}]}` var msg map[string]interface{} err := json.Unmarshal([]byte(str), &msg) if err!=nil { fmt.Println("fuck",err) } fmt.Println(msg) changes,ok := msg["changes"].([](interface{})) if !ok { fmt.Println("Can't convert msg to []interface") } for _ ,ichange := range changes { change, ok := ichange.(map[string]interface{}) if !ok { fmt.Println("cant convert ichange to map[string]interface{}") } Index, ok := change["Index"].(float64) if !ok { fmt.Println("cant convert Index to float64") } armid,ok := change["armid"].(float64) if !ok { fmt.Println("cant convert armid to float") } fmt.Println(Index,armid) } }
运行结果是:
map[changes:[map[armid:3 Index:5] map[armid:3 Index:6]]] 5 3 6 3
需要注意的是:
(1)json中的数字解码到map中统一是float64类型,如果实际中采用其它类型需要手动转换
(2)map中对应json的key是大小写敏感的,同时也没有结构体中要求的首字母大写
总结:
比较一下可以发现,在已知数据结构的情况下,采用结构体方式解码在对解码后的取值上要方便许多,而采用空接口要经过多次断言,适合使用在不知道数据格式的情况下。
有疑问加站长微信联系(非本文作者)