成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

用面向?qū)ο蟮姆绞讲僮?JSON 甚至還能做四則運(yùn)算 JSON 庫(kù)

開(kāi)發(fā) 前端
至此算是我第一次利用編譯原理的知識(shí)解決了一點(diǎn)特定領(lǐng)域問(wèn)題,在大學(xué)以及工作這些年一直覺(jué)得編譯原理比較高深,所以內(nèi)心一直是抗拒的,但經(jīng)過(guò)這段時(shí)間的學(xué)習(xí)和實(shí)踐慢慢的也掌握到了一點(diǎn)門道。

前言

在之前實(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 := gjson.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)念一想,部分場(chǎng)景我們甚至我們只需要拿到 JSON? 中的某個(gè)字段的值,這樣還需要先聲明一個(gè) struct 會(huì)略顯麻煩。

經(jīng)過(guò)查詢發(fā)現(xiàn)已經(jīng)有了一個(gè)類似的庫(kù)來(lái)解決該問(wèn)題,https://github.com/tidwall/gjson 并且 star 數(shù)還很多(甚至名字都是一樣的??),說(shuō)明這樣的需求大家還是很強(qiáng)烈的。

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

圖片

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

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

因?yàn)楣δ茴愃疲晕覅⒖剂?nbsp;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 := gjson.Get(str, "name")
assert.Equal(t, name.String(), "bob")

age := gjson.Get(str, "age")
assert.Equal(t, age.Int(), 20)

assert.Equal(t, gjson.Get(str,"skill.lang[0].go.feature[0]").String(), "goroutine")
assert.Equal(t, gjson.Get(str,"skill.lang[0].go.feature[1]").String(), "channel")
assert.Equal(t, gjson.Get(str,"skill.lang[0].go.feature[2]").String(), "simple")
assert.Equal(t, gjson.Get(str,"skill.lang[0].go.feature[3]").Bool(), true)

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

返回值參考了 tidwall? 使用了一個(gè) Result 對(duì)象,它提供了多種方法可以方便的獲取各種類型的數(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)然前提是傳入的語(yǔ)法返回的是一個(gè)合法 JSONObject 或數(shù)組。

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

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

  • 單個(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")

語(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)纳珊玫?nbsp;JSONObject 中獲取數(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? 類型為 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ò)程的源碼:

https://github.com/crossoverJie/gjson/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, "score.math[1] / score.math[0]")
assert.Equal(t, result.Int(), 2)

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

其中核心的四則運(yùn)算邏輯是由之前寫的腳本解釋器提供的:

?https://github.com/crossoverJie/gscript?

圖片

單獨(dú)提供了一個(gè)函數(shù),傳入一個(gè)四則運(yùn)算表達(dá)式返回計(jì)算結(jié)果。

由于上一版本還不支持 float,所以這次專門適配了一下。

限于篇幅,更多關(guān)于這個(gè)四則運(yùn)算的實(shí)現(xiàn)邏輯會(huì)在后面繼續(xù)分享。

總結(jié)

至此算是我第一次利用編譯原理的知識(shí)解決了一點(diǎn)特定領(lǐng)域問(wèn)題,在大學(xué)以及工作這些年一直覺(jué)得編譯原理比較高深,所以內(nèi)心一直是抗拒的,但經(jīng)過(guò)這段時(shí)間的學(xué)習(xí)和實(shí)踐慢慢的也掌握到了一點(diǎn)門道。

不過(guò)目前也只是冰山一角,后面的編譯原理后端更是要涉及到計(jì)算機(jī)底層知識(shí),所以依然任重而道遠(yuǎn)。

已上都是題外話,針對(duì)于這個(gè)庫(kù)我也會(huì)長(zhǎng)期維護(hù);為了能達(dá)到生產(chǎn)的使用要求,盡量提高了單測(cè)覆蓋率,目前是98%。

責(zé)任編輯:武曉燕 來(lái)源: crossoverJie
相關(guān)推薦

2022-07-12 08:19:16

XJSON四則運(yùn)算場(chǎng)景

2024-05-13 00:47:37

JSON對(duì)象數(shù)據(jù)

2023-09-25 09:45:01

數(shù)據(jù)模型

2011-08-18 14:05:12

NoSQL

2009-10-20 13:58:00

CCIE學(xué)習(xí)筆記

2015-06-23 13:56:30

數(shù)據(jù)庫(kù)設(shè)計(jì)面向?qū)ο?/a>

2017-09-13 10:58:51

JavaScript轉(zhuǎn)換規(guī)則

2022-10-27 10:06:16

Presto SQLAntlr大數(shù)據(jù)

2016-12-12 13:41:37

iOS簡(jiǎn)易加法開(kāi)發(fā)

2017-09-05 16:17:35

JavaScript運(yùn)算轉(zhuǎn)換

2011-05-13 11:17:18

javascript

2010-01-07 16:29:33

使用Json

2021-10-15 10:39:43

RabbitMQ隊(duì)列延遲

2021-03-26 08:41:11

Go語(yǔ)言Docker

2020-07-20 07:56:28

JavaScript開(kāi)發(fā)技術(shù)

2011-03-04 14:58:40

jqueryJSON

2013-03-27 11:33:32

iOS開(kāi)發(fā)iOSjson解析方式

2017-10-16 10:42:27

前端JavaScript浮點(diǎn)數(shù)

2021-07-27 05:04:12

python初等函數(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美日韩精品国产 | 久久久国产一区二区三区 | 91免费在线 | 男人天堂视频在线观看 | 日韩三片 | 国产精品欧美一区二区三区不卡 | 欧美日韩高清一区 | 国产亚洲精品美女久久久久久久久久 | 天堂亚洲网 | 亚洲一区二区在线播放 | 精品久久不卡 | 欧美区日韩区 | 国产精品国产成人国产三级 | 国产人久久人人人人爽 | 国产一区二区三区高清 | 久久不射电影网 | 亚洲高清三级 | a免费视频 | 伊人欧美视频 | www.亚洲成人网 | a级毛片基地 | 免费一区二区在线观看 | 国产在线一区二区三区 | 欧美激情精品久久久久久变态 | 久久9久| 日本特黄a级高清免费大片 成年人黄色小视频 | 精品伦精品一区二区三区视频 | 黄色一级大片在线免费看产 | 国产精品美女久久久久aⅴ国产馆 | 日韩一区二区三区精品 | 日韩在线观看 | 视频在线一区二区 | 国产传媒在线观看 | 日韩av啪啪网站大全免费观看 | 国产婷婷在线视频 | 乳色吐息在线观看 | 成人在线视频网站 | 亚洲一区二区三区四区五区中文 | 欧美一级黄色免费看 | 中文字幕一区在线观看视频 | 91在线视频观看免费 |