這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
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 53 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 36 3
需要注意的是:
(1)json中的數字解碼到map中統一是float64類型,如果實際中採用其它類型需要手動轉換
(2)map中對應json的key是大小寫敏感的,同時也沒有結構體中要求的首字母大寫
總結:
比較一下可以發現,在已知資料結構的情況下,採用結構體方式解碼在對解碼後的取值上要方便許多,而採用空介面要經過多次斷言,適合使用在不知道資料格式的情況下。