人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動態(tài)

go面向?qū)ο蠓绞讲僮鱆SON庫實(shí)現(xiàn)四則運(yùn)算

發(fā)布日期:2022-07-15 19:40 | 文章來源:站長之家

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

decode, err := xjson.Decode(`{"glossary":{"title":"example glossary","age":1}}`)
assert.Nil(t, err)
glossary := v["glossary"].(map[string]interface{})
assert.Equal(t, glossary["title"], "example glossary")
assert.Equal(t, glossary["age"], 1)

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

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

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

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

因?yàn)楣δ茴愃疲晕覅⒖剂?code>tidwall的API但去掉一些我覺得暫時(shí)用不上的特性,并調(diào)整了一點(diǎn)語法。

當(dāng)前這個(gè)版本只能通過確定的key加上.點(diǎn)符號訪問數(shù)據(jù),如果是數(shù)組則用[index]的方式訪問下標(biāo)。
[]符號訪問數(shù)組我覺得要更符合直覺一些。

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

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)

這樣的語法使用個(gè)人覺得還是滿符合直覺的,相信對使用者來說也比較簡單。

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

func (r Result) String() string
func (r Result) Bool() bool
func (r Result) Int() int
func (r Result) Float() float64
func (r Result) Map() map[string]interface{}
func (r Result) Array() *[]interface{}
func (r Result) Exists() bool

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

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

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

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

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

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

這次只是額外再解析剛才定義的語法為token,然后解析該token的同時(shí)再從生成好的JSONObject中獲取數(shù)據(jù)。

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

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

首先第一步是對查詢語法做詞法分析,最終得到下圖的token

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

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

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

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

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

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

有興趣的可以看下解析過程的源碼:

https://github.com/crossoverJie/xjson/blob/cfbca51cc9bc0c77e6cb9c9ad3f964b2054b3826/json.go#L46

對 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, "score.math[1] / score.math[0]")
assert.Equal(t, result.Int(), 2)

最后我還擴(kuò)展了一下語法,可以支持對JSON數(shù)據(jù)中的整形(int、float)做四則運(yùn)算,雖然這是一個(gè)小眾需求,但做完我覺得還挺有意思的,目前在市面上我還沒發(fā)現(xiàn)有類似功能的庫,可能和小眾需求有關(guān)

版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。

相關(guān)文章

實(shí)時(shí)開通

自選配置、實(shí)時(shí)開通

免備案

全球線路精選!

全天候客戶服務(wù)

7x24全年不間斷在線

專屬顧問服務(wù)

1對1客戶咨詢顧問

在線
客服

在線客服:7*24小時(shí)在線

客服
熱線

400-630-3752
7*24小時(shí)客服服務(wù)熱線

關(guān)注
微信

關(guān)注官方微信
頂部