2019独角兽企业重金招聘Python工程师标准>>>

 
  

get json values quickly

GJSON is a Go package that provides a fast and simple way to get values from a json document. It has features such as one line retrieval, dot notation paths, iteration, and parsing json lines.

Also check out SJSON for modifying json, and the JJ command line tool.

Getting Started

Installing

To start using GJSON, install Go and run go get:

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

This will retrieve the library.

Get a value

Get searches json for the specified path. A path is in dot syntax, such as "name.last" or "age". When the value is found it's returned immediately.

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())
}

This will print:

Prichard

There's also the GetMany function to get multiple values at once, and GetBytes for working with JSON byte slices.

Path Syntax

A path is a series of keys separated by a dot. A key may contain special wildcard characters '*' and '?'. To access an array value use the index as the key. To get the number of elements in an array or to access a child path, use the '#' character. The dot and wildcard characters can be escaped with '\'.

{"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"

You can also query an array for the first match by using #[...], or find all matches with #[...]#. Queries support the ==!=<<=>>= comparison operators and the simple pattern matching % operator.

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

JSON Lines

There's support for JSON Lines using the .. prefix, which treats a multilined document as an array.

For example:

{"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

The ForEachLines function will iterate through JSON lines.

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

Result Type

GJSON supports the json types stringnumberbool, and null. Arrays and Objects are returned as their raw json types.

The Result type holds one of these:

bool, for JSON booleans
float64, for JSON numbers
string, for JSON string literals
nil, for JSON null

To directly access the 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

There are a variety of handy functions that work on a result:

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

The result.Value() function returns an interface{} which requires type assertion and is one of the following Go types:

The result.Array() function returns back an array of values. If the result represents a non-existent value, then an empty array will be returned. If the result is not a JSON array, the return value will be an array containing one result.

boolean >> bool
number  >> float64
string  >> string
null    >> nil
array   >> []interface{}
object  >> map[string]interface{}

64-bit integers

The result.Int() and result.Uint() calls are capable of reading all 64 bits, allowing for large JSON integers.

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

Get nested array values

Suppose you want all the last names from the following json:

{"programmers": [{"firstName": "Janet", "lastName": "McLaughlin", }, {"firstName": "Elliotte", "lastName": "Hunter", }, {"firstName": "Jason", "lastName": "Harold", }]
}

You would use the path "programmers.#.lastName" like such:

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

You can also query an object inside an array:

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

Iterate through an object or array

The ForEach function allows for quickly iterating through an object or array. The key and value are passed to the iterator function for objects. Only the value is passed for arrays. Returning false from an iterator will stop iteration.

result := gjson.Get(json, "programmers")
result.ForEach(func(key, value gjson.Result) bool {println(value.String()) return true // keep iterating
})

Simple Parse and Get

There's a Parse(json) function that will do a simple parse, and result.Get(path) that will search a result.

For example, all of these will return the same result:

gjson.Parse(json).Get("name").Get("last")
gjson.Get(json, "name").Get("last")
gjson.Get(json, "name.last")

Check for the existence of a value

Sometimes you just want to know if a value exists.

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")
}

Validate JSON

The Get* and Parse* functions expects that the json is well-formed. Bad json will not panic, but it may return back unexpected results.

If you are consuming JSON from an unpredictable source then you may want to validate prior to using GJSON.

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

Unmarshal to a map

To unmarshal to a map[string]interface{}:

m, ok := gjson.Parse(json).Value().(map[string]interface{})
if !ok {// not a map
}

Working with Bytes

If your JSON is contained in a []byte slice, there's the GetBytes function. This is preferred over Get(string(data), path).

var json []byte = ...
result := gjson.GetBytes(json, path)

If you are using the gjson.GetBytes(json, path) function and you want to avoid converting result.Raw to a []byte, then you can use this pattern:

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)
}

This is a best-effort no allocation sub slice of the original json. This method utilizes the result.Index field, which is the position of the raw data in the original json. It's possible that the value of result.Index equals zero, in which case the result.Raw is converted to a []byte.

Get multiple values at once

The GetMany function can be used to get multiple values at the same time.

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

The return value is a []Result, which will always contain exactly the same number of items as the input paths.

Performance

Benchmarks of GJSON alongside encoding/json, ffjson, EasyJSON, jsonparser, and json-iterator

BenchmarkGJSONGet-8                  3000000        372 ns/op          0 B/op         0 allocs/op
BenchmarkGJSONUnmarshalMap-8          900000       4154 ns/op       1920 B/op        26 allocs/op
BenchmarkJSONUnmarshalMap-8           600000       9019 ns/op       3048 B/op        69 allocs/op
BenchmarkJSONDecoder-8                300000      14120 ns/op       4224 B/op       184 allocs/op
BenchmarkFFJSONLexer-8               1500000       3111 ns/op        896 B/op         8 allocs/op
BenchmarkEasyJSONLexer-8             3000000        887 ns/op        613 B/op         6 allocs/op
BenchmarkJSONParserGet-8             3000000        499 ns/op         21 B/op         0 allocs/op
BenchmarkJSONIterator-8              3000000        812 ns/op        544 B/op         9 allocs/op

JSON document used:

{"widget": {"debug": "on","window": {"title": "Sample Konfabulator Widget","name": "main_window","width": 500,"height": 500},"image": { "src": "Images/Sun.png","hOffset": 250,"vOffset": 250,"alignment": "center"},"text": {"data": "Click Here","size": 36,"style": "bold","vOffset": 100,"alignment": "center","onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"}}
}

Each operation was rotated though one of the following search paths:

widget.window.name
widget.image.hOffset
widget.text.onMouseUp

These benchmarks were run on a MacBook Pro 15" 2.8 GHz Intel Core i7 using Go 1.8 and can be be found here.

Contact

Josh Baker @tidwall

License

GJSON source code is available under the MIT License.

转载于:https://my.oschina.net/u/3553591/blog/1625530

golang的GJSON库相关推荐

  1. 再测Golang的JSON库

    2019独角兽企业重金招聘Python工程师标准>>> 写项目一直需要进行序列化,听到了,也看到了很多同学老师对各个golang的json库进行测评.那本人为什么还要继续进行这一次测 ...

  2. Golang实现requests库

    Golang实现requests库 简单的封装下,方便使用,像python的requests库一样. Github地址 Github 支持 GET.POST.PUT.DELETE applicatio ...

  3. go语言调用c 的头文件 so,Golang生成共享库(shared library)以及Golang生成C可调用的动态库.so和静态库.a...

    Golang类似于C的静态语言,效率也接近于C,如果Golang也可以导出可供C调用的库,那可以和很多高级语言say goodbye了,goodbye似乎又有点武断,但至少说,Golang可以做很多事 ...

  4. 用 Golang 实现矩阵运算库

    用 Golang 实现矩阵运算库 天下文章一大抄 抄过来的 转载的 别来沾边

  5. GoLang之标准库net/http包源码

    GoLang之标准库net/http包源码 目录 GoLang之标准库net/http包源码 1.net/http包介绍 2.http.ListenAndServe函数 3.http.Handle函数 ...

  6. Golang高性能日志库zap + lumberjack 日志切割组件详解

    文章篇幅较长,可以先收藏防止迷路~ 目录 zap日志库 1. why zap? 2. 简单使用 3. 自定义logger例子 4. Gin项目使用zap 6. lumberjack 日志切割组件 za ...

  7. Golang的viper库

    Golang的viper库 1.作用 viper 是一个配置解决方案,拥有丰富的特性: 支持 JSON/TOML/YAML/HCL/envfile/Java properties 等多种格式的配置文件 ...

  8. golang桌面gui库fyne使用

    golang桌面gui库fyne使用 使用 初始项目 新建项目文件夹fyna 执行go mod init 执行go get fyne.io/fyne/v2 执行go mod tidy 创建main.g ...

  9. GoLang之标准库strings包

    文章目录 GoLang之标准库strings包 1.函数介绍 2.EqualFold 3.TrimSpace 4.HasPrefix 5.HasSuffix 6.Index 7.LastIndex 8 ...

最新文章

  1. 安装envi出现cannot find lincese_Ubuntu 16.04 安装 CUDA10.1 (解决循环登陆的问题)
  2. 【算法与数据结构】在n个数中取第k大的数(基础篇)
  3. SAP 电商云 Spartacus UI 的 CORS 设置
  4. cloudfoundry_在Cloudfoundry上部署RESTful服务
  5. 图深度学习-第2部分
  6. 【leetcode】ZigZag Conversion
  7. redis的java客户端名称_java里常用的redis客户端简介
  8. 敏捷开发系列学习总结(15)——Spotify敏捷模式详解三部曲第三篇:工程文化
  9. Gradle_04_解决多项目同级依赖时找不到符号的异常
  10. [译] 第二天:AngularJS - 认识AngularJS
  11. 强大的Mockito测试框架
  12. EIGRP中AD与FD的区别
  13. 微信公众号分销商城(源码+数据库+文档)
  14. 通信原理中的erf/erfc函数
  15. FreeCAD源码分析: PartDesign模块
  16. 微信小程序跳转公众号图文内容
  17. GPU显存占满但利用率却很低
  18. OBCA认证知识点-part3
  19. Accuracy, Precision, Recall和F1-score解释
  20. 做PPT浪费时间,那是因为你不知道这四个工具

热门文章

  1. opencv python 灰度图转三通道彩色图
  2. 【SPSS】2.定义变量
  3. 钢材规格解读的软件_钢材的理论重量计算软件
  4. emmet插件的导入与实用
  5. 全国计算机二级web考试试题,全国计算机二级Web模拟试题及答案(1)
  6. ANSYS Mechanical联合ANSYS nCode DesignLife 在疲劳中的应用
  7. 计算机桌面怎么设置时钟,桌面时钟怎么设置-老司机教你电脑闹钟怎么设置
  8. 创建Vue-Cli脚手架
  9. 以下是MySQL增删改查的常用语句汇总
  10. Oracle之字符串去重统计