Introduction
目前有80%的API支持json數據協議
json協議為一種資料傳輸的標準,不同語言之間溝通的橋樑
將golang中數據類型,如struct
,map
等,使用json序列化,與其他語言進行交互
json數據協議
導入包:import "encoding/json"
json序列化
序列化:json.Marshal(data interface{})
打包成json字符串,參數可傳入各種不同的數據結構
json序列化結構體
因為json為外部的package,因此欲被外部包訪問的情況下,在定義結構體時需注意字段名(屬性)須為大寫 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package mainimport ( "encoding/json" "fmt" "os" ) type User struct { UserName string NickName string Age int Birth string Gender string Email string Phone string } func main () { Taroballz := &User{ UserName:"Curtis" , NickName:"Taroballz" , Age:18 , Birth:"2000/12/12" , Gender:"Male" , Email:"[email protected] " , Phone:"1001234567" , } result, err := json.Marshal(Taroballz) if err != nil { fmt.Fprintf(os.Stderr,"json encoding Failed:%s" ,err) return } fmt.Println("json encoding result:" ,result) fmt.Println("json string is " , string (result)) }
json打包的結果為[]byte
類型,透過string()
方法轉換為字符串
result 1 2 json encoding result: [123 34 85 115 101 114 78 97 109 101 34 58 34 67 117 114 116 105 115 34 44 34 78 105 99 107 78 97 109 101 34 58 34 84 97 114 111 98 97 108 108 122 34 44 34 65 103 101 34 58 49 56 44 34 66 105 114 116 104 34 58 34 50 48 48 48 47 49 50 47 49 50 34 44 34 71 101 110 100 101 114 34 58 34 77 97 108 101 34 44 34 69 109 97 105 108 34 58 34 115 116 117 100 121 64 103 111 108 97 110 103 46 99 111 109 34 44 34 80 104 111 110 101 34 58 34 49 48 48 49 50 51 52 53 54 55 34 125] json string is {"UserName":"Curtis","NickName":"Taroballz","Age":18,"Birth":"2000/12/12","Gender":"Male","Email":"[email protected] ","Phone":"1001234567"}
tips 可使用json.MarshalIndent(欲格式化數據,空值替換,縮進替換)
進行格式化輸出 顯示結果會較清晰,但與Marshal方法無異1 result, err := json.MarshalIndent(Taroballz,"" ," " )
result 1 2 3 4 5 6 7 8 9 json string is { "username": "Curtis", "nickname": "Taroballz", "Age": 18, "Birth": "2000/12/12", "Gender": "Male", "Email": "[email protected] ", "Phone": "1001234567" }
tag
透過反射(reflect)的tag將字段從大寫轉為小寫
格式為json:"value"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package mainimport ( "encoding/json" "fmt" "os" ) type User struct { UserName string `json:"username"` NickName string `json:"nickname"` Age int Birth string Gender string Email string Phone string } func main () { Taroballz := &User{ UserName:"Curtis" , NickName:"Taroballz" , Age:18 , Birth:"2000/12/12" , Gender:"Male" , Email:"[email protected] " , Phone:"1001234567" , } result, err := json.Marshal(Taroballz) if err != nil { fmt.Fprintf(os.Stderr,"json encoding Failed:%s" ,err) return } fmt.Println("json string is " , string (result)) }
result 1 json string is {"username":"Curtis","nickname":"Taroballz","Age":18,"Birth":"2000/12/12","Gender":"Male","Email":"[email protected] ","Phone":"1001234567"}
透過tag可將原本需大寫的字段名在json的格式中轉為小寫
tips
若是編碼後的json不想輸出至終端可使用json:"-"
作為tag
若是bool類型的true,false;float及int類型的數字要使用字符串作為json輸出可使用json:",string"
作為tag
json序列化map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package mainimport ( "encoding/json" "fmt" "os" ) func testJsonMap () { var Tom map [string ]interface {} = map [string ]interface {}{"Age" :18 } Tom["Name" ] = "Tom" Tom["gender" ] = "Male" data,err := json.Marshal(Tom) if err != nil { fmt.Fprintln(os.Stderr,"json encoding failed:" ,err) return } fmt.Println("json encoding result:" ,string (data)) } func main () { testJsonMap() }
result 1 json encoding result: {"Age":18,"Name":"Tom","gender":"Male"}
json序列化切片(slice)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package mainimport ( "encoding/json" "fmt" "os" ) func testJsonSlice () { var userinfo []map [string ]interface {} userinfo = make ([]map [string ]interface {},0 ) userinfo = append (userinfo,map [string ]interface {}{"Name" :"Amy" }) userinfo[0 ]["Age" ] = 18 fmt.Println(cap (userinfo)) userinfo = append (userinfo,map [string ]interface {}{"Name" :"Tom" }) data, err := json.Marshal(userinfo) if err != nil { fmt.Fprintln(os.Stderr,"json encoding failed:" ,err) return } fmt.Println("json encoding result:" ,string (data)) } func main () { testJsonSlice() }
result 1 2 1 json encoding result: [{"Age":18,"Name":"Amy"},{"Name":"Tom"}]
json反序列化 在別人系統或是不同語言中拿到json的數據類型並反序列化成golang中的數據類型,並進行其他操作
反序列化:json.UnMarshal(data []byte, v interface{})
將json字符串反序列化成golang的數據類型
data
為要反序列化的json字符串
v
為不同數據類型的實例
反序列化結構體
在反序列化之前要保證反序列化的類型 及字段 跟欲接收的容器是一樣的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 package mainimport ( "encoding/json" "fmt" ) type User struct { UserName string `json:"username"` NickName string `json:"nickname"` Age int Birth string Gender string Email string Phone string } func testStruct () (Error error, user string ) { Taroballz := &User{ UserName:"Curtis" , NickName:"Taroballz" , Age:18 , Birth:"2000/12/12" , Gender:"Male" , Email:"[email protected] " , Phone:"1001234567" , } result, err := json.Marshal(Taroballz) if err != nil { Error = fmt.Errorf("json encoding Failed:%s" ,err) return } user = string (result) return } func testUnMarshallStruct (data string ) (ret User, err error) { var container User err = json.Unmarshal([]byte (data),&container) if err != nil { err = fmt.Errorf("UnMarshal Failed" ) return } ret = container return } func main () { err,data := testStruct() if err != nil { fmt.Println(err) return } result ,err := testUnMarshallStruct(data) if err != nil { fmt.Println(err) return } fmt.Println("result is" ,result) }
result
tips
UnMarshall只會解析所需要的字段置入結構體中
反序列化map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 package mainimport ( "encoding/json" "fmt" ) func testJsonMap () (ret string , error error) { var Tom map [string ]interface {} = map [string ]interface {}{"Age" :18 } Tom["Name" ] = "Tom" Tom["gender" ] = "Male" data,err := json.Marshal(Tom) if err != nil { error = fmt.Errorf("json encoding failed" ) return } ret = string (data) return } func testUnMarshalMap (data string ) (ret map [string ]interface {},error error) { var container map [string ]interface {} err := json.Unmarshal([]byte (data),&container) if err != nil { error = fmt.Errorf("Unmarshal failed:" ,err) return } ret = container return } func main () { data,err := testJsonMap() if err != nil { fmt.Println(err) return } result ,err := testUnMarshalMap(data) if err != nil { fmt.Println(err) return } fmt.Println("result is" ,result) }
可以看到在創建接收map類型的變量時,並沒有使用make()
初始化map,亦就是說map在json.unmarshal()
函數中才分配,只需將對應類型的變量傳入就好
往map中插入數據時,才會因為map是引用類型 無須取址,但是改變map本身所儲存的資料 則需取址
result 1 result is map[Name:Tom gender:Male Age:18]
tips
在json數據的量比較大的情況下,標準庫encoding/json
會不敷使用
這時可以使用ffjson進行序列化及反序列化
go get github.com/pquerna/ffjson/ffjson
其使用方法與encoding/json
使用方法差不多
其速度為encoding/json
的3到4倍