主頁 > 知識庫 > 使用Go語言解析動(dòng)態(tài)JSON格式的方法

使用Go語言解析動(dòng)態(tài)JSON格式的方法

熱門標(biāo)簽:鄭州亮點(diǎn)科技用的什么外呼系統(tǒng) 濱州自動(dòng)電銷機(jī)器人排名 惠州電銷防封電話卡 汕頭小型外呼系統(tǒng) 阿里云ai電話機(jī)器人 浙江高頻外呼系統(tǒng)多少錢一個(gè)月 建造者2地圖標(biāo)注 釘釘有地圖標(biāo)注功能嗎 黃岡人工智能電銷機(jī)器人哪個(gè)好

通常使用Golang encoding/json 標(biāo)準(zhǔn)庫可以方便的編碼/解析JSON數(shù)據(jù),但是前提需要定義struct數(shù)據(jù)結(jié)構(gòu)。特別是解析未知結(jié)構(gòu)的JSON數(shù)據(jù)時(shí),原有方法很難滿足需求了,本文主要介紹動(dòng)態(tài)解析JSON格式。

Go語言的JSON 庫

Go語言自帶的JSON轉(zhuǎn)換庫為 encoding/json

1.1)其中把對象轉(zhuǎn)換為JSON的方法(函數(shù))為 json.Marshal(),其函數(shù)原型如下

func Marshal(v  interface{}) ([]byte, error)

也就是說,這個(gè)函數(shù)接收任意類型的數(shù)據(jù) v,并轉(zhuǎn)換為字節(jié)數(shù)組類型,返回值就是我們想要的JSON數(shù)據(jù)和一個(gè)錯(cuò)誤代碼。當(dāng)轉(zhuǎn)換成功的時(shí)候,這個(gè)錯(cuò)誤代碼為nil

在進(jìn)行對象轉(zhuǎn)換為 JSON 的過程中,會(huì)遵循如下幾條規(guī)則:

  1. 布爾型轉(zhuǎn)換為 JSON 后仍是布爾型 , 如true -> true
  2. 浮點(diǎn)型和整數(shù)型轉(zhuǎn)換后為JSON里面的常規(guī)數(shù)字,如 1.23 -> 1.23
  3. 字符串將以UTF-8編碼轉(zhuǎn)化輸出為Unicode字符集的字符串,特殊字符比如將會(huì)被轉(zhuǎn)義為\u003c
  4. 數(shù)組和切片被轉(zhuǎn)換為JSON 里面的數(shù)組,[]byte類會(huì)被轉(zhuǎn)換為base64編碼后的字符串,slice的零值被轉(zhuǎn)換為null
  5. 結(jié)構(gòu)體會(huì)轉(zhuǎn)化為JSON對象,并且只有結(jié)構(gòu)體里邊以大寫字母開頭的可被導(dǎo)出的字段才會(huì)被轉(zhuǎn)化輸出,而這些可導(dǎo)出的字段會(huì)作為JSON對象的字符串索引
  6. 轉(zhuǎn)化一個(gè)map 類型的數(shù)據(jù)結(jié)構(gòu)時(shí),該數(shù)據(jù)的類型必須是 map[string]T(T 可以是encoding/json 包支持的任意數(shù)據(jù)類型)

1.2)把 JSON 轉(zhuǎn)換回對象的方法(函數(shù))為 json.Unmarshal(),其函數(shù)原型如下

func Unmarshal(data [] byte, v interface{}) error

這個(gè)函數(shù)會(huì)把傳入的 data 作為一個(gè)JSON來進(jìn)行解析,解析后的數(shù)據(jù)存儲(chǔ)在參數(shù) v 中。這個(gè)參數(shù) v 也是任意類型的參數(shù)(但一定是一個(gè)類型的指針),原因是我們在是以此函數(shù)進(jìn)行JSON 解析的時(shí)候,這個(gè)函數(shù)不知道這個(gè)傳入?yún)?shù)的具體類型,所以它需要接收所有的類型。

那么,在進(jìn)行解析的時(shí)候,如果JSON 和 對象的結(jié)構(gòu)不對口會(huì)發(fā)生什么呢,這就需要解析函數(shù)json.Unmarshal()遵循以下規(guī)則

json.Unmarshal() 函數(shù)會(huì)根據(jù)一個(gè)約定的順序查找目標(biāo)結(jié)構(gòu)中的字段,如果找到一個(gè)即發(fā)生匹配。那什么是找到了呢?關(guān)于“找到了”又有如下的規(guī)則:假設(shè)一個(gè)JSON對象有個(gè)名為"Foo"的索引,要將"Foo"所對應(yīng)的值填充到目標(biāo)結(jié)構(gòu)體的目標(biāo)字段上,json.Unmarshal() 將會(huì)遵循如下順序進(jìn)行查找匹配

  1. § 一個(gè)包含F(xiàn)oo 標(biāo)簽的字段
  2. §  一個(gè)名為Foo 的字段
  3. § 一個(gè)名為Foo 或者Foo 或者除了首字母其他字母不區(qū)分大小寫的名為Foo 的字段。 這些字段在類型聲明中必須都是以大寫字母開頭、可被導(dǎo)出的字段。

注意:如果JSON中的字段在Go目標(biāo)類型中不存在,json.Unmarshal() 函數(shù)在解碼過程中會(huì)丟棄該字段。

當(dāng)JSON 的結(jié)構(gòu)是未知的時(shí)候,會(huì)遵循如下規(guī)則:

  1. § JSON中的布爾值將會(huì)轉(zhuǎn)換為Go中的bool類型
  2. § 數(shù)值會(huì)被轉(zhuǎn)換為Go中的float64類型
  3. § 字符串轉(zhuǎn)換后還是string類型
  4. § JSON數(shù)組會(huì)轉(zhuǎn)換為[]interface{} 類型
  5. § JSON對象會(huì)轉(zhuǎn)換為map[string]interface{}類型
  6. § null值會(huì)轉(zhuǎn)換為nil

注意:在Go的標(biāo)準(zhǔn)庫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字段的時(shí)候,可以在字段后面添加tag,來控制encode/decode的過程:是否要 decode/encode 某個(gè)字段,JSON 中的字段名稱是什么。字段名首字母控制字段的可見性,若要輸出到JSON,首字母需要大寫。

三種tag:

- :不要解析這個(gè)字段

omitempty :當(dāng)字段為空(默認(rèn)值)時(shí),不要解析這個(gè)字段。比如 false、0、nil、長度為 0 的 array,map,slice,string

FieldName :當(dāng)解析 json 的時(shí)候,使用這個(gè)名字

舉例來說吧:

// 解析的時(shí)候忽略該字段。默認(rèn)情況下會(huì)解析這個(gè)字段,因?yàn)樗谴髮懽帜搁_頭的
Field int `json:"-"`
// 解析(encode/decode) 的時(shí)候,使用 `other_name`,而不是 `Field`
Field int `json:"other_name"`
// 解析的時(shí)候使用 `other_name`,如果struct 中這個(gè)值為空,就忽略它
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、動(dòng)態(tài)解析

動(dòng)態(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")
 }
 //獲取某個(gè)字段值
 s, err := js.Get("test").Get("string").String()
 if err != nil {
  panic(err)
 }
 fmt.Println(s)
 //檢查某個(gè)字段是否存在
 _, 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 具體什么類型實(shí)現(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í)有所幫助,也希望大家多多支持腳本之家。

您可能感興趣的文章:
  • NodeJS 實(shí)現(xiàn)多語言的示例代碼
  • Thinkphp搭建包括JS多語言的多語言項(xiàng)目實(shí)現(xiàn)方法
  • JS(jQuery)實(shí)現(xiàn)聊天接收到消息語言自動(dòng)提醒功能詳解【提示“您有新的消息請注意查收”】
  • 實(shí)例說明js腳本語言和php腳本語言的區(qū)別
  • 易語言調(diào)用JS取隨機(jī)數(shù)
  • 易語言調(diào)用JS代碼方法總結(jié)
  • Go語言的JSON處理詳解
  • JS如何在不同平臺(tái)實(shí)現(xiàn)多語言方式

標(biāo)簽:駐馬店 泰安 晉中 昭通 瀘州 東營 阿壩 滄州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《使用Go語言解析動(dòng)態(tài)JSON格式的方法》,本文關(guān)鍵詞  使用,語言,解析,動(dòng)態(tài),JSON,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《使用Go語言解析動(dòng)態(tài)JSON格式的方法》相關(guān)的同類信息!
  • 本頁收集關(guān)于使用Go語言解析動(dòng)態(tài)JSON格式的方法的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章