Go中使用gjson來(lái)操作JSON數(shù)據(jù)的實(shí)現(xiàn)
項(xiàng)目地址:https://github.com/tidwall/gjson
下載:
$ go get -u github.com/tidwall/gjson
獲取值
Get查詢指定路徑, 通過(guò).來(lái)區(qū)分. 比如"name.last"或者"age". 如果找到了匹配路徑, 將返回結(jié)果.
package main
import "github.com/tidwall/gjson"
const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
func main() {
value := gjson.Get(json, "name.last")
println(value.String())
}
輸出結(jié)果:
Prichard
同時(shí)有 GetMany 方法批量獲取值, 也有 GetBytes 方法獲取字節(jié)切片.
路徑解析
路徑是一系列被.分隔的key拼接而成. 路徑可能包含通配符'*'和'?'. 通過(guò)下標(biāo)訪問(wèn)數(shù)組值. 通過(guò)'#'來(lái)獲取值在元素中的排位或訪問(wèn)子路徑. .和通配符可以通過(guò)''來(lái)轉(zhuǎn)義.
{
"name": {"first": "Tom", "last": "Anderson"},
"age":37,
"children": ["Sara","Alex","Jack"],
"fav.movie": "Deer Hunter",
"friends": [
{"first": "Dale", "last": "Murphy", "age": 44},
{"first": "Roger", "last": "Craig", "age": 68},
{"first": "Jane", "last": "Murphy", "age": 47}
]
}
"name.last" >> "Anderson" "age" >> 37 "children" >> ["Sara","Alex","Jack"] "children.#" >> 3 "children.1" >> "Alex" "child*.2" >> "Jack" "c?ildren.0" >> "Sara" "fav\.movie" >> "Deer Hunter" "friends.#.first" >> ["Dale","Roger","Jane"] "friends.1.last" >> "Craig"
你同樣能通過(guò)#[...]來(lái)查詢數(shù)組中的第一個(gè)匹配的項(xiàng), 或通過(guò)'#[...]#'查詢所有匹配的項(xiàng). 查詢支持==, !=, <, <=, >, >=比較運(yùn)算符和'%'模糊匹配.
friends.#[last=="Murphy"].first >> "Dale" friends.#[last=="Murphy"]#.first >> ["Dale","Jane"] friends.#[age>45]#.last >> ["Craig","Murphy"] friends.#[first%"D*"].last >> "Murphy"
JSON 行
同樣支持JSON Lines, 使用 .. 前綴, 把多行文檔視作數(shù)組. 比如:
{"name": "Gilbert", "age": 61}
{"name": "Alexa", "age": 34}
{"name": "May", "age": 57}
{"name": "Deloise", "age": 44}
..# >> 4
..1 >> {"name": "Alexa", "age": 34}
..3 >> {"name": "Deloise", "age": 44}
..#.name >> ["Gilbert","Alexa","May","Deloise"]
..#[name="May"].age >> 57
ForEachLines 方法可以迭代json.
gjson.ForEachLine(json, func(line gjson.Result) bool{
println(line.String())
return true
})
Result Type
GJSON支持json類(lèi)型包括 string, number, bool, and null. 數(shù)組和對(duì)象被擋住基礎(chǔ)類(lèi)型返回. Result 持有如下其中一種類(lèi)型:
bool, for JSON booleans float64, for JSON numbers string, for JSON string literals nil, for JSON null
直接訪問(wèn)value:
result.Type // can be String, Number, True, False, Null, or JSON result.Str // holds the string result.Num // holds the float64 number result.Raw // holds the raw json result.Index // index of raw value in original json, zero means index unknown
有各種各樣的方便的函數(shù)可以獲取結(jié)果:
result.Exists() bool
result.Value() interface{}
result.Int() int64
result.Uint() uint64
result.Float() float64
result.String() string
result.Bool() bool
result.Time() time.Time
result.Array() []gjson.Result
result.Map() map[string]gjson.Result
result.Get(path string) Result
result.ForEach(iterator func(key, value Result) bool)
result.Less(token Result, caseSensitive bool) bool
result.Value() 方法返回 interface{} Go基本類(lèi)型之一. result.Array() 方法返回一組值. 如果結(jié)果是不存在的值, 將會(huì)返回空數(shù)組. 如果結(jié)果不是JSON數(shù)組, 將會(huì)返回只包含一個(gè)值的數(shù)組.
boolean >> bool
number >> float64
string >> string
null >> nil
array >> []interface{}
object >> map[string]interface{}
64-bit integers
result.Int() 和 result.Uint() 返回的是64位大數(shù)字.
result.Int() int64 // -9223372036854775808 to 9223372036854775807 result.Uint() int64 // 0 to 18446744073709551615
讀取嵌套數(shù)組
假如你想從下列json獲取所有的lastName:
{
"programmers": [
{
"firstName": "Janet",
"lastName": "McLaughlin",
}, {
"firstName": "Elliotte",
"lastName": "Hunter",
}, {
"firstName": "Jason",
"lastName": "Harold",
}
]
}
你可以使用如下路徑programmers.#.lastName:
result := gjson.Get(json, "programmers.#.lastName")
for _, name := range result.Array() {
println(name.String())
}
你同樣能獲取數(shù)組里的對(duì)象:
name := gjson.Get(json, `programmers.#[lastName="Hunter"].firstName`) println(name.String()) // prints "Elliotte"
對(duì)象或數(shù)組迭代
ForEach方法允許你快速的迭代對(duì)象或數(shù)組. key和value被傳遞給對(duì)象的迭代器函數(shù). 只有value被傳遞給數(shù)組. 迭代器返回false將會(huì)終止迭代.
簡(jiǎn)易的Parse和Get
Parse(json)方法可以簡(jiǎn)單的分析json, result.Get(path)查詢結(jié)果. 比如, 下面的幾種情況都將返回相同的結(jié)果:
gjson.Parse(json).Get("name").Get("last")
gjson.Get(json, "name").Get("last")
gjson.Get(json, "name.last")
檢查value是否存在
有時(shí)你想要知道值是否存在.
value := gjson.Get(json, "name.last")
if !value.Exists() {
println("no last name")
} else {
println(value.String())
}
// Or as one step
if gjson.Get(json, "name.last").Exists() {
println("has a last name")
}
驗(yàn)證JSON
Get* 和 Parse* 方法預(yù)期json格式是正常的, 如果不正常, 將會(huì)返回不可預(yù)料的結(jié)果. 如果你讀取的json來(lái)源不可預(yù)料, 那么你可以通過(guò)GJSON這么事先驗(yàn)證.
if !gjson.Valid(json) {
return errors.New("invalid json")
}
value := gjson.Get(json, "name.last")
反序列化到map
反序列化到map[string]interface{}:
m, ok := gjson.Parse(json).Value().(map[string]interface{})
if !ok {
// not a map
}
## 處理Bytes
如果你的JSON包含字節(jié)數(shù)組切片, 與其調(diào)用`Get(string(data), path)`, 不如調(diào)用[GetBytes](https://godoc.org/github.com/tidwall/gjson#GetBytes)方法更優(yōu).
```go
var json []byte = ...
result := gjson.GetBytes(json, path)
如果你在使用gjson.GetBytes(json, path)方法, 并且你想避免從result.Raw 轉(zhuǎn)換到 []byte, 你可以使用這種模式:
var json []byte = ...
result := gjson.GetBytes(json, path)
var raw []byte
if result.Index > 0 {
raw = json[result.Index:result.Index+len(result.Raw)]
} else {
raw = []byte(result.Raw)
}
這是最好的模式, 不會(huì)為子切片重新分配內(nèi)存. 這個(gè)模式使用了result.Index字段, 它直接指向了raw data所處原來(lái)json中的位置. 如果result.Raw是轉(zhuǎn)換成[]byte的, result.Index將會(huì)為0.
一次獲取多個(gè)值
GetMany方法可以用于同時(shí)獲取多個(gè)值.
results := gjson.GetMany(json, "name.first", "name.last", "age")
返回值是[]Result類(lèi)型, 總是返回正傳入路徑個(gè)數(shù)的數(shù)量.
到此這篇關(guān)于Go中使用gjson來(lái)操作JSON數(shù)據(jù)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Go gjson操作JSON內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go中使用操作符進(jìn)行數(shù)學(xué)運(yùn)算的示例代碼
在編程中有效地執(zhí)行數(shù)學(xué)運(yùn)算是一項(xiàng)需要開(kāi)發(fā)的重要技能,本文主要介紹了Go中使用操作符進(jìn)行數(shù)學(xué)運(yùn)算的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10
Go語(yǔ)言入門(mén)Go?Web?Fiber框架快速了解
這篇文章主要為大家介紹了Go語(yǔ)言入門(mén)Go?Web?Fiber框架的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
一文帶你了解Go語(yǔ)言中time包的時(shí)間常用操作
在日常開(kāi)發(fā)中,我們避免不了時(shí)間的使用,我們可能需要獲取當(dāng)前時(shí)間,然后格式化保存,也可能需要在時(shí)間類(lèi)型與字符串類(lèi)型之間相互轉(zhuǎn)換等。本文將會(huì)對(duì)?Go?time?包里面的常用函數(shù)和方法進(jìn)行介紹,需要的可以參考一下2022-12-12
簡(jiǎn)單聊聊Go語(yǔ)言中空結(jié)構(gòu)體和空字符串的特殊之處
在日常的編程過(guò)程中,大家應(yīng)該經(jīng)常能遇到各種”空“吧,比如空指針、空結(jié)構(gòu)體、空字符串等,本文就以?Go?語(yǔ)言為例,一起來(lái)看看空結(jié)構(gòu)體和空字符串在?Go?語(yǔ)言中的特殊之處吧2024-03-03
Golang實(shí)現(xiàn)http文件上傳小功能的案例
這篇文章主要介紹了Golang實(shí)現(xiàn)http文件上傳小功能的案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05
使用Go和Gorm實(shí)現(xiàn)讀取SQLCipher加密數(shù)據(jù)庫(kù)
本文檔主要描述通過(guò)Go和Gorm實(shí)現(xiàn)生成和讀取SQLCipher加密數(shù)據(jù)庫(kù)以及其中踩的一些坑,文章通過(guò)代碼示例講解的非常詳細(xì), 對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-06-06
golang利用unsafe操作未導(dǎo)出變量-Pointer使用詳解
這篇文章主要給大家介紹了關(guān)于golang利用unsafe操作未導(dǎo)出變量-Pointer使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08

