十分鐘教你寫一個 Json 解析庫

fpdk4226 7年前發布 | 26K 次閱讀 JSON Go語言 Google Go/Golang開發

json是在開發當中一種常見的數據結構,本身它的協議棧就是很簡潔的,如果有興趣的同學,可以參考RFC4627文檔,本文的最后我會附上這部分的鏈接,方便大家查看。那么在go項目的開發當中,比如最常見的web項目,我們需用到json來傳遞數據,那么必然就會面對將json object,轉換成go中對應的數據結構的需求。無需擔心的是,go提供了encoding/json解析包,我們接下來要做的工作就是在此基礎上做一定封裝,以方便自己使用。同時這個庫也是特別適合新手來練手使用,因為它設計到了go中的map,struct,assert,interface{}...,所以對于加深對go基礎的理解也很有幫助,甚至你還可以寫出更好的呢!

項目地址: https://github.com/liyu4/ljson

開始

定義一個全局對象,data為interface{}類型意味這可以存儲任何類型的數據。

typeJs struct {
datainterface{}
}

工廠模式實例化Js對象,這里我們將需要反序列化的data數據,先轉換成byte數組, 然后將其解析到&f指向的值中,也就是說f是包含了我們反序列化得到的數據。本文接下來的部分就是對這個f的操作。

funcNewJson(datastring) *Js {
j:= new(Js)
 varfinterface{}
err:=json.Unmarshal([]byte(data), &f)
 if nil !=err{
 returnj
 }
j.data=f
 returnj
}

獲取map,這里我們使用了斷言,判斷interface{}是否是map[string]interface{}類型

// return map in Go
func(j*Js) GetMapData()map[string]interface{} {
 ifm,ok:= (j.data).(map[string]interface{});ok{
 returnm
 }
 return nil
}

獲取key對應的value

// Acoording to the key of the returned data information , return js.data
// if you know json is an object
func(j*Js) Get(keystring) *Js {
m:=j.GetMapData()
 ifv,ok:=m[key];ok{
j.data=v
 returnj
 }
j.data= nil
 returnj
}

或者value根據下標,這里指的是從slice和map中,你懂的,這里有一個點需要小心一下,就是map返回的順序是不固定的

// GetIndex get []interface or map in Go
func(j*Js) GetIndex(iint) *Js {
num:=i- 1
 ifm,ok:= (j.data).([]interface{});ok{
 ifnum<=len(m)-1{
v:=m[num]
j.data=v
 }else{
j.data= nil
 }
 returnj
 }

 {
 ifm,ok:= (j.data).(map[string]interface{});ok{
 varn= 0
 vardata=make(map[string]interface{})
 fori,v:=range m{
 ifn==num{
 switchvv:=v.(type) {
 casefloat64:
data[i] =strconv.FormatFloat(vv, 'f', -1, 64)
j.data=data
 returnj
 case string:
data[i] =vv
j.data=data
 returnj
 case []interface{}:
j.data=vv
 returnj
 }
 }
n++
 }
 }
 }
j.data= nil
 returnj
}

自定義key和下標返回value,注意錯誤的處理

// The data must be []interface{}, According to your custom number to return key adn array data
func(j*Js) GetKey(keystring,iint) (*Js,error) {
num:=i- 1
 ifi>len((j.data).([]interface{})) {
 return nil,errors.New("index out of range list")
 }
 ifm,ok:= (j.data).([]interface{});ok{
v:=m[num].(map[string]interface{})
 ifh,ok:=v[key];ok{
j.data=h
 returnj, nil
 }
 }
j.data= nil
 returnj, nil
}

遞歸map

// According to the custom of the PATH to fing element
// You can use function this to find recursive map
func(j*Js) GetPath(args...string) *Js {
d:=j
 fori:=range args{
m:=d.GetMapData()

 ifval,ok:=m[args[i]];ok{
d.data=val
 } else {
d.data= nil
 returnd
 }
 }
 returnd
}

String方法,相信大家也看到了我們的slice和map中的值都是interface{},轉換陳string能方便我們的操作。

// String return string
func(j*Js) String() string {
 ifm,ok:=j.data.(string);ok{
 returnm
 }
 ifm,ok:=j.data.(float64);ok{
 returnstrconv.FormatFloat(m, 'f', -1, 64)
 }
 return ""
}

返回key和value數組 []string

func(j*Js) ToArray() (k,d[]string) {
 varkey,data[]string
 ifm,ok:= (j.data).([]interface{});ok{
 for_,value:=range m{
 forindex,v:=range value.(map[string]interface{}) {
 switchvv:=v.(type) {
 casefloat64:
data=append(data,strconv.FormatFloat(vv, 'f', -1, 64))
key=append(key,index)
 case string:
data=append(data,vv)
key=append(key,index)
 }
 }
 }
 returnkey,data
 }
 ifm,ok:= (j.data).(map[string]interface{});ok{
 forindex,v:=range m{
 switchvv:=v.(type) {
 casefloat64:
data=append(data,strconv.FormatFloat(vv, 'f', -1, 64))
key=append(key,index)
 case string:
data=append(data,vv)
key=append(key,index)
 }
 }
 returnkey,data
 }
 return nil, nil
}

返回一個[]string

// Array return array
func(j*Js) Array() ([]string,error) {
 ifa,ok:= (j.data).([]interface{});ok{
array:=make([]string, 0)
 for_,v:=range a{
 switchvv:=v.(type) {
 casefloat64:
array=append(array,strconv.FormatFloat(vv, 'f', -1, 64))
 case string:
array=append(array,vv)
 }

 }
 returnarray, nil
 }
 return nil,errors.New("type assertion to []interface{} failed")
}

一個漂亮但是沒啥子用的調試函數

//for test
func(j*Js) Type() {
fmt.Println(reflect.TypeOf(j.data))
}

至此我們就完成了一個可以部署在生產環境中的json library,這個項目是小巧和堅實的,希望大家能自己動手寫寫,最好是在下雨的星期天下午。

參考

RFC4627 Json in Go

 

來自:https://www.zybuluo.com/aliasliyu4/note/601706

 

 本文由用戶 fpdk4226 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!