项目地址:https://github.com/tidwall/gjson
下载:
$ go get -u github.com/tidwall/gjson
获取值
Get查询指定路径, 通过.来区分. 比如”name.last”或者”age”. 如果找到了匹配路径, 将返回结果.
package mainimport "github.com/tidwall/gjson"const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`func main() {value := gjson.Get(json, "name.last")println(value.String())}
输出结果:
Prichard
同时有 GetMany 方法批量获取值, 也有 GetBytes 方法获取字节切片.
路径解析
路径是一系列被.分隔的key拼接而成.
路径可能包含通配符’*’和’?’.
通过下标访问数组值.
通过’#’来获取值在元素中的排位或访问子路径..和通配符可以通过’\’来转义.
{"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"
你同样能通过#[...]来查询数组中的第一个匹配的项, 或通过’#[…]#’查询所有匹配的项.
查询支持==, !=, <, <=, >, >=比较运算符和’%’模糊匹配.
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, 使用 .. 前缀, 把多行文档视作数组.
比如:
{"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类型包括 string, number, bool, and null. 数组和对象被挡住基础类型返回.Result 持有如下其中一种类型:
bool, for JSON booleansfloat64, for JSON numbersstring, for JSON string literalsnil, for JSON null
直接访问value:
result.Type // can be String, Number, True, False, Null, or JSONresult.Str // holds the stringresult.Num // holds the float64 numberresult.Raw // holds the raw jsonresult.Index // index of raw value in original json, zero means index unknown
有各种各样的方便的函数可以获取结果:
result.Exists() boolresult.Value() interface{}result.Int() int64result.Uint() uint64result.Float() float64result.String() stringresult.Bool() boolresult.Time() time.Timeresult.Array() []gjson.Resultresult.Map() map[string]gjson.Resultresult.Get(path string) Resultresult.ForEach(iterator func(key, value Result) bool)result.Less(token Result, caseSensitive bool) bool
result.Value() 方法返回 interface{} Go基本类型之一.result.Array() 方法返回一组值.
如果结果是不存在的值, 将会返回空数组.
如果结果不是JSON数组, 将会返回只包含一个值的数组.
boolean >> boolnumber >> float64string >> stringnull >> nilarray >> []interface{}object >> map[string]interface{}
64-bit integers
result.Int() 和 result.Uint() 返回的是64位大数字.
result.Int() int64 // -9223372036854775808 to 9223372036854775807result.Uint() int64 // 0 to 18446744073709551615
读取嵌套数组
假如你想从下列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())}
你同样能获取数组里的对象:
name := gjson.Get(json, `programmers.#[lastName="Hunter"].firstName`)println(name.String()) // prints "Elliotte"
对象或数组迭代
ForEach方法允许你快速的迭代对象或数组.
key和value被传递给对象的迭代器函数.
只有value被传递给数组. 迭代器返回false将会终止迭代.
简易的Parse和Get
Parse(json)方法可以简单的分析json, result.Get(path)查询结果.
比如, 下面的几种情况都将返回相同的结果:
gjson.Parse(json).Get("name").Get("last")gjson.Get(json, "name").Get("last")gjson.Get(json, "name.last")
检查value是否存在
有时你想要知道值是否存在.
value := gjson.Get(json, "name.last")if !value.Exists() {println("no last name")} else {println(value.String())}// Or as one stepif gjson.Get(json, "name.last").Exists() {println("has a last name")}
验证JSON
Get* 和 Parse* 方法预期json格式是正常的, 如果不正常, 将会返回不可预料的结果.
如果你读取的json来源不可预料, 那么你可以通过GJSON这么事先验证.
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包含字节数组切片, 与其调用`Get(string(data), path)`, 不如调用[GetBytes](https://godoc.org/github.com/tidwall/gjson#GetBytes)方法更优.```govar json []byte = ...result := gjson.GetBytes(json, path)
如果你在使用gjson.GetBytes(json, path)方法, 并且你想避免从result.Raw 转换到 []byte, 你可以使用这种模式:
var json []byte = ...result := gjson.GetBytes(json, path)var raw []byteif result.Index > 0 {raw = json[result.Index:result.Index+len(result.Raw)]} else {raw = []byte(result.Raw)}
这是最好的模式, 不会为子切片重新分配内存. 这个模式使用了result.Index字段, 它直接指向了raw data所处原来json中的位置.
如果result.Raw是转换成[]byte的, result.Index将会为0.
一次获取多个值
GetMany方法可以用于同时获取多个值.
results := gjson.GetMany(json, "name.first", "name.last", "age")
返回值是[]Result类型, 总是返回正传入路径个数的数量.
