go面向?qū)ο蠓绞讲僮鱆SON庫(kù)實(shí)現(xiàn)四則運(yùn)算_第1頁(yè)
go面向?qū)ο蠓绞讲僮鱆SON庫(kù)實(shí)現(xiàn)四則運(yùn)算_第2頁(yè)
go面向?qū)ο蠓绞讲僮鱆SON庫(kù)實(shí)現(xiàn)四則運(yùn)算_第3頁(yè)
go面向?qū)ο蠓绞讲僮鱆SON庫(kù)實(shí)現(xiàn)四則運(yùn)算_第4頁(yè)
go面向?qū)ο蠓绞讲僮鱆SON庫(kù)實(shí)現(xiàn)四則運(yùn)算_第5頁(yè)
已閱讀5頁(yè),還剩1頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第go面向?qū)ο蠓绞讲僮鱆SON庫(kù)實(shí)現(xiàn)四則運(yùn)算目錄前言面向?qū)ο蟮姆绞讲僮鱆SON實(shí)現(xiàn)原理對(duì)JSON做四則運(yùn)算總結(jié)

前言

在之前實(shí)現(xiàn)的JSON解析器中當(dāng)時(shí)只實(shí)現(xiàn)了將一個(gè)JSON字符串轉(zhuǎn)換為一個(gè)JSONObject,并沒(méi)有將其映射為一個(gè)具體的struct;如果想要獲取值就需要先做斷言將其轉(zhuǎn)換為map或者是切片再來(lái)獲,會(huì)比較麻煩。

decode,err:=xjson.Decode(`{"glossary":{"title":"exampleglossary","age":1}}`)

assert.Nil(t,err)

glossary:=v["glossary"].(map[string]interface{})

assert.Equal(t,glossary["title"],"exampleglossary")

assert.Equal(t,glossary["age"],1)

但其實(shí)轉(zhuǎn)念一想,部分場(chǎng)景我們甚至我們只需要拿到JSON中的某個(gè)字段的值,這樣還需要先聲明一個(gè)struct會(huì)略顯麻煩。

于是我也打算增加類(lèi)似的功能,使用方式如下:

最后還加上了一個(gè)四則運(yùn)算的功能。

面向?qū)ο蟮姆绞讲僮鱆SON

因?yàn)楣δ茴?lèi)似,所以我參考了tidwall的API但去掉一些我覺(jué)得暫時(shí)用不上的特性,并調(diào)整了一點(diǎn)語(yǔ)法。

當(dāng)前這個(gè)版本只能通過(guò)確定的key加上.點(diǎn)符號(hào)訪問(wèn)數(shù)據(jù),如果是數(shù)組則用[index]的方式訪問(wèn)下標(biāo)。

[]符號(hào)訪問(wèn)數(shù)組我覺(jué)得要更符合直覺(jué)一些。

以下是一個(gè)包含多重嵌套JSON的訪問(wèn)示例:

str:=`

"name":"bob",

"age":20,

"skill":{

"lang":[

"go":{

"feature":[

"goroutine",

"channel",

"simple",

true

name:=xjson.Get(str,"name")

assert.Equal(t,name.String(),"bob")

age:=xjson.Get(str,"age")

assert.Equal(t,age.Int(),20)

assert.Equal(t,xjson.Get(str,"skill.lang[0].go.feature[0]").String(),"goroutine")

assert.Equal(t,xjson.Get(str,"skill.lang[0].go.feature[1]").String(),"channel")

assert.Equal(t,xjson.Get(str,"skill.lang[0].go.feature[2]").String(),"simple")

assert.Equal(t,xjson.Get(str,"skill.lang[0].go.feature[3]").Bool(),true)

這樣的語(yǔ)法使用個(gè)人覺(jué)得還是滿符合直覺(jué)的,相信對(duì)使用者來(lái)說(shuō)也比較簡(jiǎn)單。

返回值參考了tidwall使用了一個(gè)Result對(duì)象,它提供了多種方法可以方便的獲取各種類(lèi)型的數(shù)據(jù)

func(rResult)String()string

func(rResult)Bool()bool

func(rResult)Int()int

func(rResult)Float()float64

func(rResult)Map()map[string]interface{}

func(rResult)Array()*[]interface{}

func(rResult)Exists()bool

比如使用Map()/Array()這兩個(gè)函數(shù)可以將JSON數(shù)據(jù)映射到map和切片中,當(dāng)然前提是傳入的語(yǔ)法返回的是一個(gè)合法JSONObject或數(shù)組。

實(shí)現(xiàn)原理

在實(shí)現(xiàn)之前需要先定義一個(gè)基本語(yǔ)法,主要支持以下四種用法:

單個(gè)key的查詢:Get(json,name)嵌套查詢:Get(json,)數(shù)組查詢:Get(json,obj.array[0])數(shù)組嵌套查詢:Get(json,obj.array[0].obj2.obj3[1].name)

語(yǔ)法很簡(jiǎn)單,符合我們?nèi)粘=佑|到語(yǔ)法規(guī)則,這樣便可以訪問(wèn)到JSON數(shù)據(jù)中的任何一個(gè)值。

其實(shí)實(shí)現(xiàn)過(guò)程也不復(fù)雜,我們已經(jīng)在上一文中實(shí)現(xiàn)將JSON字符串轉(zhuǎn)換為一個(gè)JSONObject了。

這次只是額外再解析剛才定義的語(yǔ)法為token,然后解析該token的同時(shí)再?gòu)纳珊玫腏SONObject中獲取數(shù)據(jù)。

最后在解析完token時(shí)拿到的JSONObject數(shù)據(jù)返回即可。

我們以這段查詢代碼為例:

首先第一步是對(duì)查詢語(yǔ)法做詞法分析,最終得到下圖的token。

在詞法分析過(guò)程中也可以做簡(jiǎn)單的語(yǔ)法校驗(yàn);比如如果包含數(shù)組查詢,并不是以]符號(hào)結(jié)尾時(shí)就拋出語(yǔ)法錯(cuò)誤。

接著我們遍歷語(yǔ)法的token。如下圖所示:

每當(dāng)遍歷到token類(lèi)型為Key時(shí)便從當(dāng)前的JSONObject對(duì)象中獲取數(shù)據(jù),并用獲取到的值替覆蓋為當(dāng)前的JSONObject。

其中每當(dāng)遇到.[]這樣的token時(shí)便消耗掉,直到我們將token遍歷完畢,這時(shí)將當(dāng)前JSONObject返回即可。

在遍歷過(guò)程中當(dāng)遇到非法格式時(shí),比如obj_list[1.]便會(huì)返回一個(gè)空的JSONObject。

語(yǔ)法校驗(yàn)這點(diǎn)其實(shí)也很容易辦到,因?yàn)楦鶕?jù)我們的語(yǔ)法規(guī)則,Array中的index后一定緊接的是一個(gè)EndArray,只要不是一個(gè)EndArray便能知道語(yǔ)法不合法了。

有興趣的可以看下解析過(guò)程的源碼:

/crossoverJie/xjson/blob/cfbca51cc9bc0c77e6cb9c9ad3f964b2054b3826/json.go#L46

對(duì)JSON做四則運(yùn)算

str:=`{"name":"bob","age":10,"magic":10.1,"score":{"math":[1,2]}}`

result:=GetWithArithmetic(str,"(age+age)*age+magic")

assert.Equal(t,result.Float(),210.1)

result=GetWithArithmetic(str,"(age+age)*age")

assert.Equal(t,result.Int(),200)

result=GetWithArithmetic(str,"(age+age)*age+score.math[0]")

assert.Equal(t,result.Int(),201)

result=GetWithArithmetic(str,"(age+age)*age-score.math[0]")

assert.Equal(t,result.Int(),199)

result=GetWithArithmetic(str,"

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論