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

用面向對象的方式操作 JSON 甚至還能做四則運算 JSON 庫

開發 前端
至此算是我第一次利用編譯原理的知識解決了一點特定領域問題,在大學以及工作這些年一直覺得編譯原理比較高深,所以內心一直是抗拒的,但經過這段時間的學習和實踐慢慢的也掌握到了一點門道。

前言

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

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)

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

經過查詢發現已經有了一個類似的庫來解決該問題,https://github.com/tidwall/gjson 并且 star 數還很多(甚至名字都是一樣的??),說明這樣的需求大家還是很強烈的。

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

圖片

最后還加上了一個四則運算的功能。

面向對象的方式操作 JSON

因為功能類似,所以我參考了 tidwall? 的 API 但去掉一些我覺得暫時用不上的特性,并調整了一點語法。

當前這個版本只能通過確定的 key? 加上 .? 點符號訪問數據,如果是數組則用 [index]? 的方式訪問下標。[] 符號訪問數組我覺得要更符合直覺一些。

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

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)

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

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

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()? 這兩個函數可以將 JSON? 數據映射到 map? 和切片中,當然前提是傳入的語法返回的是一個合法 JSONObject 或數組。

實現原理

在實現之前需要先定義一個基本語法,主要支持以下四種用法:

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

語法很簡單,符合我們日常接觸到語法規則,這樣便可以訪問到 JSON 數據中的任何一個值。

其實實現過程也不復雜,我們已經在上一文中實現將 JSON? 字符串轉換為一個 JSONObject 了。

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

最后在解析完 token? 時拿到的 JSONObject 數據返回即可。


圖片

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

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

圖片

在詞法分析過程中也可以做簡單的語法校驗;比如如果包含數組查詢,并不是以 ] 符號結尾時就拋出語法錯誤。

圖片

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

圖片

每當遍歷到 token? 類型為 Key 時便從當前的 JSONObject 對象中獲取數據,并用獲取到的值替覆蓋為當前的 JSONObject。

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

在遍歷過程中當遇到非法格式時,比如 obj_list[1.]? 便會返回一個空的 JSONObject。

語法校驗這點其實也很容易辦到,因為根據我們的語法規則,Array? 中的 index? 后一定緊接的是一個 EndArray?,只要不是一個 EndArray 便能知道語法不合法了。

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

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

對 JSON 做四則運算

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)

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

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

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

圖片

單獨提供了一個函數,傳入一個四則運算表達式返回計算結果。

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

限于篇幅,更多關于這個四則運算的實現邏輯會在后面繼續分享。

總結

至此算是我第一次利用編譯原理的知識解決了一點特定領域問題,在大學以及工作這些年一直覺得編譯原理比較高深,所以內心一直是抗拒的,但經過這段時間的學習和實踐慢慢的也掌握到了一點門道。

不過目前也只是冰山一角,后面的編譯原理后端更是要涉及到計算機底層知識,所以依然任重而道遠。

已上都是題外話,針對于這個庫我也會長期維護;為了能達到生產的使用要求,盡量提高了單測覆蓋率,目前是98%。

責任編輯:武曉燕 來源: crossoverJie
相關推薦

2022-07-12 08:19:16

XJSON四則運算場景

2024-05-13 00:47:37

JSON對象數據

2023-09-25 09:45:01

數據模型

2011-08-18 14:05:12

NoSQL

2009-10-20 13:58:00

CCIE學習筆記

2015-06-23 13:56:30

數據庫設計面向對象

2017-09-13 10:58:51

JavaScript轉換規則

2022-10-27 10:06:16

Presto SQLAntlr大數據

2016-12-12 13:41:37

iOS簡易加法開發

2017-09-05 16:17:35

JavaScript運算轉換

2011-05-13 11:17:18

javascript

2010-01-07 16:29:33

使用Json

2021-10-15 10:39:43

RabbitMQ隊列延遲

2021-03-26 08:41:11

Go語言Docker

2020-07-20 07:56:28

JavaScript開發技術

2011-03-04 14:58:40

jqueryJSON

2013-03-27 11:33:32

iOS開發iOSjson解析方式

2017-10-16 10:42:27

前端JavaScript浮點數

2021-07-27 05:04:12

python初等函數
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产综合在线视频 | 视频1区2区| 97影院在线午夜 | 亚洲激情一区二区 | 久久国产精彩视频 | 国产精品永久 | 亚洲成人精品一区 | 久久一 | 久久亚洲精品久久国产一区二区 | 日韩一级黄色毛片 | 欧美亚洲高清 | 日韩欧美亚洲一区 | 天天曰天天曰 | 成人性视频在线播放 | 精品国产视频 | 精品国产31久久久久久 | 国产h视频| 国产不卡在线观看 | 国产精品久久久久久久久大全 | 亚洲精品在线免费 | 日韩午夜| 欧美黄页| 午夜伦4480yy私人影院 | 2018国产大陆天天弄 | 日本特黄a级高清免费大片 特黄色一级毛片 | 性生生活大片免费看视频 | 精品中文字幕视频 | 国产精品日韩在线观看 | 爱高潮www亚洲精品 中文字幕免费视频 | 国产精品1区2区3区 中文字幕一区二区三区四区 | 精品久久久久久红码专区 | 国产亚洲精品精品国产亚洲综合 | 91视频国产精品 | 亚洲精品在线免费观看视频 | 久久综合狠狠综合久久综合88 | 在线免费观看毛片 | 日韩成人免费av | 亚洲三级免费看 | 天天视频一区二区三区 | 日韩av大片免费看 | 国产高清视频在线观看播放 |