通常使用Golang encoding/json 標準庫可以方便的編碼/解析JSON數(shù)據(jù),但是前提需要定義struct數(shù)據(jù)結(jié)構(gòu)。特別是解析未知結(jié)構(gòu)的JSON數(shù)據(jù)時,原有方法很難滿足需求了,本文主要介紹動態(tài)解析JSON格式。
桃山網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),桃山網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為桃山成百上千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)營銷網(wǎng)站建設(shè)要多少錢,請找那個售后服務(wù)好的桃山做網(wǎng)站的公司定做!
Go語言的JSON 庫
Go語言自帶的JSON轉(zhuǎn)換庫為 encoding/json
1.1)其中把對象轉(zhuǎn)換為JSON的方法(函數(shù))為 json.Marshal(),其函數(shù)原型如下
func Marshal(v interface{}) ([]byte, error)
也就是說,這個函數(shù)接收任意類型的數(shù)據(jù) v,并轉(zhuǎn)換為字節(jié)數(shù)組類型,返回值就是我們想要的JSON數(shù)據(jù)和一個錯誤代碼。當轉(zhuǎn)換成功的時候,這個錯誤代碼為nil
在進行對象轉(zhuǎn)換為 JSON 的過程中,會遵循如下幾條規(guī)則:
1.2)把 JSON 轉(zhuǎn)換回對象的方法(函數(shù))為 json.Unmarshal(),其函數(shù)原型如下
func Unmarshal(data [] byte, v interface{}) error
這個函數(shù)會把傳入的 data 作為一個JSON來進行解析,解析后的數(shù)據(jù)存儲在參數(shù) v 中。這個參數(shù) v 也是任意類型的參數(shù)(但一定是一個類型的指針),原因是我們在是以此函數(shù)進行JSON 解析的時候,這個函數(shù)不知道這個傳入?yún)?shù)的具體類型,所以它需要接收所有的類型。
那么,在進行解析的時候,如果JSON 和 對象的結(jié)構(gòu)不對口會發(fā)生什么呢,這就需要解析函數(shù)json.Unmarshal()遵循以下規(guī)則
json.Unmarshal() 函數(shù)會根據(jù)一個約定的順序查找目標結(jié)構(gòu)中的字段,如果找到一個即發(fā)生匹配。那什么是找到了呢?關(guān)于“找到了”又有如下的規(guī)則:假設(shè)一個JSON對象有個名為"Foo"的索引,要將"Foo"所對應(yīng)的值填充到目標結(jié)構(gòu)體的目標字段上,json.Unmarshal() 將會遵循如下順序進行查找匹配
注意:如果JSON中的字段在Go目標類型中不存在,json.Unmarshal() 函數(shù)在解碼過程中會丟棄該字段。
當JSON 的結(jié)構(gòu)是未知的時候,會遵循如下規(guī)則:
注意:在Go的標準庫encoding/json包中,允許使用map[string]interface{}和[]interface{} 類型的值來分別存放未知結(jié)構(gòu)的JSON對象或數(shù)組
1、傳統(tǒng)方法
比如 User 數(shù)據(jù)結(jié)構(gòu)如下:
type User struct { Name string `json:"name"` Age int `json:"age"` }
在定義struct字段的時候,可以在字段后面添加tag,來控制encode/decode的過程:是否要 decode/encode 某個字段,JSON 中的字段名稱是什么。字段名首字母控制字段的可見性,若要輸出到JSON,首字母需要大寫。
三種tag:
-
:不要解析這個字段
omitempty
:當字段為空(默認值)時,不要解析這個字段。比如 false、0、nil、長度為 0 的 array,map,slice,string
FieldName
:當解析 json 的時候,使用這個名字
舉例來說吧:
// 解析的時候忽略該字段。默認情況下會解析這個字段,因為它是大寫字母開頭的 Field int `json:"-"` // 解析(encode/decode) 的時候,使用 `other_name`,而不是 `Field` Field int `json:"other_name"` // 解析的時候使用 `other_name`,如果struct 中這個值為空,就忽略它 Field int `json:"other_name,omitempty"`
(1)encode
user := User{Name: "test", Age:23} data, err := json.Marshal(user) if err != nil { fmt.Println(string(data)) }
data 就是 []byte 類型的數(shù)組,里面包含了解析為 JSON 之后的數(shù)據(jù),可以使用string(data)轉(zhuǎn)型為string。
(2)decode
要把JSON數(shù)據(jù)轉(zhuǎn)換成Go類型的值(Decode),可以使用 json.Unmarshal 。
var user User err = json.Unmarshal(data, &user) if err != nil { fmt.Errorf("Can not decode data: %v\n", err) }
2、動態(tài)解析
動態(tài)JSON結(jié)構(gòu)未知,若使用前面方法需要事先定義數(shù)據(jù)結(jié)構(gòu),這與PHP/Python JSON處理非常不同。若不考慮性能,使用simplejson。
(1)simplejson
js, err := simplejson.NewJson([]byte(`{ "test": { "string_array": ["asdf", "zxcv"], "array": [1, "2", 3], "arraywithsubs": [{"subkeyone": 1}, "bignum": 9223372036854775807, "string": "simplejson", "bool": true } }`)) if err != nil { panic("json format error") } //獲取某個字段值 s, err := js.Get("test").Get("string").String() if err != nil { panic(err) } fmt.Println(s) //檢查某個字段是否存在 _, ok := js.Get("test").CheckGet("string2") if ok { fmt.Println("存在!") } else { fmt.Println("不存在") }
(2)interface
比如JSON有以下兩種類型:
{"Type":"sound","Msg":{"Description":"dynamite","Authority":"the Bruce Dickinson"}} {"Type":"cowbell","Msg":{"More":true}}
Msg 具體什么類型實現(xiàn)無法判斷, Msg being a map[string]interface{} :
type Envelope struct { Type string Msg interface{} } var env Envelope if err := json.Unmarshal([]byte(input), &env); err != nil { log.Fatal(err) } // for the love of Gopher DO NOT DO THIS var desc string = env.Msg.(map[string]interface{})["description"].(string) fmt.Println(desc)
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。