项目地址:https://github.com/tidwall/gjson

下载:

  1. $ go get -u github.com/tidwall/gjson

获取值

Get查询指定路径, 通过.来区分. 比如”name.last”或者”age”. 如果找到了匹配路径, 将返回结果.

  1. package main
  2. import "github.com/tidwall/gjson"
  3. const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
  4. func main() {
  5. value := gjson.Get(json, "name.last")
  6. println(value.String())
  7. }

输出结果:

  1. Prichard

同时有 GetMany 方法批量获取值, 也有 GetBytes 方法获取字节切片.

路径解析

路径是一系列被.分隔的key拼接而成.
路径可能包含通配符’*’和’?’.
通过下标访问数组值.
通过’#’来获取值在元素中的排位或访问子路径.
.和通配符可以通过’\’来转义.

  1. {
  2. "name": {"first": "Tom", "last": "Anderson"},
  3. "age":37,
  4. "children": ["Sara","Alex","Jack"],
  5. "fav.movie": "Deer Hunter",
  6. "friends": [
  7. {"first": "Dale", "last": "Murphy", "age": 44},
  8. {"first": "Roger", "last": "Craig", "age": 68},
  9. {"first": "Jane", "last": "Murphy", "age": 47}
  10. ]
  11. }
  1. "name.last" >> "Anderson"
  2. "age" >> 37
  3. "children" >> ["Sara","Alex","Jack"]
  4. "children.#" >> 3
  5. "children.1" >> "Alex"
  6. "child*.2" >> "Jack"
  7. "c?ildren.0" >> "Sara"
  8. "fav\.movie" >> "Deer Hunter"
  9. "friends.#.first" >> ["Dale","Roger","Jane"]
  10. "friends.1.last" >> "Craig"

你同样能通过#[...]来查询数组中的第一个匹配的项, 或通过’#[…]#’查询所有匹配的项.
查询支持==, !=, <, <=, >, >=比较运算符和’%’模糊匹配.

  1. friends.#[last=="Murphy"].first >> "Dale"
  2. friends.#[last=="Murphy"]#.first >> ["Dale","Jane"]
  3. friends.#[age>45]#.last >> ["Craig","Murphy"]
  4. friends.#[first%"D*"].last >> "Murphy"

JSON 行

同样支持JSON Lines, 使用 .. 前缀, 把多行文档视作数组.
比如:

  1. {"name": "Gilbert", "age": 61}
  2. {"name": "Alexa", "age": 34}
  3. {"name": "May", "age": 57}
  4. {"name": "Deloise", "age": 44}
  1. ..# >> 4
  2. ..1 >> {"name": "Alexa", "age": 34}
  3. ..3 >> {"name": "Deloise", "age": 44}
  4. ..#.name >> ["Gilbert","Alexa","May","Deloise"]
  5. ..#[name="May"].age >> 57

ForEachLines 方法可以迭代json.

  1. gjson.ForEachLine(json, func(line gjson.Result) bool{
  2. println(line.String())
  3. return true
  4. })

Result Type

GJSON支持json类型包括 string, number, bool, and null. 数组和对象被挡住基础类型返回.
Result 持有如下其中一种类型:

  1. bool, for JSON booleans
  2. float64, for JSON numbers
  3. string, for JSON string literals
  4. nil, for JSON null

直接访问value:

  1. result.Type // can be String, Number, True, False, Null, or JSON
  2. result.Str // holds the string
  3. result.Num // holds the float64 number
  4. result.Raw // holds the raw json
  5. result.Index // index of raw value in original json, zero means index unknown

有各种各样的方便的函数可以获取结果:

  1. result.Exists() bool
  2. result.Value() interface{}
  3. result.Int() int64
  4. result.Uint() uint64
  5. result.Float() float64
  6. result.String() string
  7. result.Bool() bool
  8. result.Time() time.Time
  9. result.Array() []gjson.Result
  10. result.Map() map[string]gjson.Result
  11. result.Get(path string) Result
  12. result.ForEach(iterator func(key, value Result) bool)
  13. result.Less(token Result, caseSensitive bool) bool

result.Value() 方法返回 interface{} Go基本类型之一.
result.Array() 方法返回一组值.
如果结果是不存在的值, 将会返回空数组.
如果结果不是JSON数组, 将会返回只包含一个值的数组.

  1. boolean >> bool
  2. number >> float64
  3. string >> string
  4. null >> nil
  5. array >> []interface{}
  6. object >> map[string]interface{}

64-bit integers

result.Int()result.Uint() 返回的是64位大数字.

  1. result.Int() int64 // -9223372036854775808 to 9223372036854775807
  2. result.Uint() int64 // 0 to 18446744073709551615

读取嵌套数组

假如你想从下列json获取所有的lastName:

  1. {
  2. "programmers": [
  3. {
  4. "firstName": "Janet",
  5. "lastName": "McLaughlin",
  6. }, {
  7. "firstName": "Elliotte",
  8. "lastName": "Hunter",
  9. }, {
  10. "firstName": "Jason",
  11. "lastName": "Harold",
  12. }
  13. ]
  14. }

你可以使用如下路径programmers.#.lastName:

  1. result := gjson.Get(json, "programmers.#.lastName")
  2. for _, name := range result.Array() {
  3. println(name.String())
  4. }

你同样能获取数组里的对象:

  1. name := gjson.Get(json, `programmers.#[lastName="Hunter"].firstName`)
  2. println(name.String()) // prints "Elliotte"

对象或数组迭代

ForEach方法允许你快速的迭代对象或数组.
key和value被传递给对象的迭代器函数.
只有value被传递给数组. 迭代器返回false将会终止迭代.

简易的Parse和Get

Parse(json)方法可以简单的分析json, result.Get(path)查询结果.
比如, 下面的几种情况都将返回相同的结果:

  1. gjson.Parse(json).Get("name").Get("last")
  2. gjson.Get(json, "name").Get("last")
  3. gjson.Get(json, "name.last")

检查value是否存在

有时你想要知道值是否存在.

  1. value := gjson.Get(json, "name.last")
  2. if !value.Exists() {
  3. println("no last name")
  4. } else {
  5. println(value.String())
  6. }
  7. // Or as one step
  8. if gjson.Get(json, "name.last").Exists() {
  9. println("has a last name")
  10. }

验证JSON

Get*Parse* 方法预期json格式是正常的, 如果不正常, 将会返回不可预料的结果.
如果你读取的json来源不可预料, 那么你可以通过GJSON这么事先验证.

  1. if !gjson.Valid(json) {
  2. return errors.New("invalid json")
  3. }
  4. value := gjson.Get(json, "name.last")

反序列化到map

反序列化到map[string]interface{}:

  1. m, ok := gjson.Parse(json).Value().(map[string]interface{})
  2. if !ok {
  3. // not a map
  4. }
  5. ## 处理Bytes
  6. 如果你的JSON包含字节数组切片, 与其调用`Get(string(data), path)`, 不如调用[GetBytes](https://godoc.org/github.com/tidwall/gjson#GetBytes)方法更优.
  7. ```go
  8. var json []byte = ...
  9. result := gjson.GetBytes(json, path)

如果你在使用gjson.GetBytes(json, path)方法, 并且你想避免从result.Raw 转换到 []byte, 你可以使用这种模式:

  1. var json []byte = ...
  2. result := gjson.GetBytes(json, path)
  3. var raw []byte
  4. if result.Index > 0 {
  5. raw = json[result.Index:result.Index+len(result.Raw)]
  6. } else {
  7. raw = []byte(result.Raw)
  8. }

这是最好的模式, 不会为子切片重新分配内存. 这个模式使用了result.Index字段, 它直接指向了raw data所处原来json中的位置.
如果result.Raw是转换成[]byte的, result.Index将会为0.

一次获取多个值

GetMany方法可以用于同时获取多个值.

  1. results := gjson.GetMany(json, "name.first", "name.last", "age")

返回值是[]Result类型, 总是返回正传入路径个数的数量.