2016-09-12 07:25:09 +03:00
< p align = "center" >
< img
src="logo.png"
width="240" height="78" border="0" alt="GJSON">
< br >
2017-09-30 04:10:12 +03:00
< a href = "https://travis-ci.org/tidwall/gjson" > < img src = "https://img.shields.io/travis/tidwall/gjson.svg?style=flat-square" alt = "Build Status" > < / a >
2016-09-12 07:25:09 +03:00
< a href = "https://godoc.org/github.com/tidwall/gjson" > < img src = "https://img.shields.io/badge/api-reference-blue.svg?style=flat-square" alt = "GoDoc" > < / a >
2018-10-18 16:30:41 +03:00
< a href = "http://tidwall.com/gjson-play" > < img src = "https://img.shields.io/badge/%F0%9F%8F%90-playground-9900cc.svg?style=flat-square" alt = "GJSON Playground" > < / a >
2016-09-12 07:25:09 +03:00
< / p >
2016-12-12 20:33:28 +03:00
2018-10-18 16:30:41 +03:00
< p align = "center" > get json values quickly< / a > < / p >
2017-09-30 04:10:12 +03:00
GJSON is a Go package that provides a [fast ](#performance ) and [simple ](#get-a-value ) way to get values from a json document.
2018-10-18 16:30:41 +03:00
It has features such as [one line retrieval ](#get-a-value ), [dot notation paths ](#path-syntax ), [iteration ](#iterate-through-an-object-or-array ), and [parsing json lines ](#json-lines ).
Also check out [SJSON ](https://github.com/tidwall/sjson ) for modifying json, and the [JJ ](https://github.com/tidwall/jj ) command line tool.
2016-09-12 07:25:09 +03:00
Getting Started
===============
## Installing
To start using GJSON, install Go and run `go get` :
```sh
$ go get -u github.com/tidwall/gjson
```
This will retrieve the library.
## Get a value
2018-10-18 16:30:41 +03:00
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.
2016-09-12 07:25:09 +03:00
```go
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())
}
```
This will print:
```
Prichard
```
2016-12-12 20:33:28 +03:00
*There's also the [GetMany ](#get-multiple-values-at-once ) function to get multiple values at once, and [GetBytes ](#working-with-bytes ) for working with JSON byte slices.*
2016-09-12 07:25:09 +03:00
## 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.
2017-09-30 04:10:12 +03:00
The dot and wildcard characters can be escaped with '\\'.
2016-09-12 07:25:09 +03:00
```json
{
"name": {"first": "Tom", "last": "Anderson"},
"age":37,
"children": ["Sara","Alex","Jack"],
"fav.movie": "Deer Hunter",
"friends": [
2016-12-12 20:33:28 +03:00
{"first": "Dale", "last": "Murphy", "age": 44},
{"first": "Roger", "last": "Craig", "age": 68},
{"first": "Jane", "last": "Murphy", "age": 47}
2016-09-12 07:25:09 +03:00
]
}
```
```
"name.last" >> "Anderson"
"age" >> 37
2016-12-12 20:33:28 +03:00
"children" >> ["Sara","Alex","Jack"]
2016-09-12 07:25:09 +03:00
"children.#" >> 3
"children.1" >> "Alex"
"child*.2" >> "Jack"
"c?ildren.0" >> "Sara"
"fav\.movie" >> "Deer Hunter"
2016-12-12 20:33:28 +03:00
"friends.#.first" >> ["Dale","Roger","Jane"]
2016-09-12 07:25:09 +03:00
"friends.1.last" >> "Craig"
```
2016-12-12 20:33:28 +03:00
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.
2016-09-12 07:25:09 +03:00
```
2016-12-12 20:33:28 +03:00
friends.#[last=="Murphy"].first >> "Dale"
friends.#[last=="Murphy"]#.first >> ["Dale","Jane"]
friends.#[age>45]#.last >> ["Craig","Murphy"]
friends.#[first%"D*"].last >> "Murphy"
2016-09-12 07:25:09 +03:00
```
2018-10-18 16:30:41 +03:00
## JSON Lines
There's support for [JSON Lines ](http://jsonlines.org/ ) 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.
```go
gjson.ForEachLine(json, func(line gjson.Result) bool{
println(line.String())
return true
})
```
2016-09-12 07:25:09 +03:00
## Result Type
GJSON supports the json types `string` , `number` , `bool` , 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:
```go
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
2016-12-12 20:33:28 +03:00
result.Index // index of raw value in original json, zero means index unknown
2016-09-12 07:25:09 +03:00
```
There are a variety of handy functions that work on a result:
```go
2017-09-30 04:10:12 +03:00
result.Exists() bool
2016-09-12 07:25:09 +03:00
result.Value() interface{}
result.Int() int64
2016-12-12 20:33:28 +03:00
result.Uint() uint64
2016-09-12 07:25:09 +03:00
result.Float() float64
result.String() string
result.Bool() bool
2017-09-30 04:10:12 +03:00
result.Time() time.Time
2016-09-12 07:25:09 +03:00
result.Array() []gjson.Result
result.Map() map[string]gjson.Result
result.Get(path string) Result
2016-12-12 20:33:28 +03:00
result.ForEach(iterator func(key, value Result) bool)
result.Less(token Result, caseSensitive bool) bool
2016-09-12 07:25:09 +03:00
```
The `result.Value()` function returns an `interface{}` which requires type assertion and is one of the following Go types:
2016-12-12 20:33:28 +03:00
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.
2016-09-12 07:25:09 +03:00
```go
boolean >> bool
number >> float64
string >> string
null >> nil
array >> []interface{}
object >> map[string]interface{}
```
2018-10-18 16:30:41 +03:00
### 64-bit integers
The `result.Int()` and `result.Uint()` calls are capable of reading all 64 bits, allowing for large JSON integers.
```go
result.Int() int64 // -9223372036854775808 to 9223372036854775807
result.Uint() int64 // 0 to 18446744073709551615
```
2016-09-12 07:25:09 +03:00
## Get nested array values
Suppose you want all the last names from the following json:
```json
{
"programmers": [
{
"firstName": "Janet",
"lastName": "McLaughlin",
}, {
"firstName": "Elliotte",
"lastName": "Hunter",
}, {
"firstName": "Jason",
"lastName": "Harold",
}
]
2017-09-30 04:10:12 +03:00
}
2016-09-12 07:25:09 +03:00
```
You would use the path "programmers.#.lastName" like such:
```go
result := gjson.Get(json, "programmers.#.lastName")
2017-09-30 04:10:12 +03:00
for _, name := range result.Array() {
2016-09-12 07:25:09 +03:00
println(name.String())
}
```
You can also query an object inside an array:
```go
name := gjson.Get(json, `programmers.#[lastName="Hunter"].firstName` )
println(name.String()) // prints "Elliotte"
```
2016-12-12 20:33:28 +03:00
## 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.
```go
result := gjson.Get(json, "programmers")
2017-09-30 04:10:12 +03:00
result.ForEach(func(key, value gjson.Result) bool {
2016-12-12 20:33:28 +03:00
println(value.String())
return true // keep iterating
})
```
2016-09-12 07:25:09 +03:00
## 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:
```go
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
2016-12-12 20:33:28 +03:00
Sometimes you just want to know if a value exists.
2016-09-12 07:25:09 +03:00
```go
value := gjson.Get(json, "name.last")
if !value.Exists() {
println("no last name")
} else {
println(value.String())
}
// Or as one step
2017-09-30 04:10:12 +03:00
if gjson.Get(json, "name.last").Exists() {
2016-09-12 07:25:09 +03:00
println("has a last name")
}
```
2018-10-18 16:30:41 +03:00
## Validate JSON
2017-09-30 04:10:12 +03:00
2018-10-18 16:30:41 +03:00
The `Get*` and `Parse*` functions expects that the json is well-formed. Bad json will not panic, but it may return back unexpected results.
2017-09-30 04:10:12 +03:00
2018-10-18 16:30:41 +03:00
If you are consuming JSON from an unpredictable source then you may want to validate prior to using GJSON.
2017-09-30 04:10:12 +03:00
```go
2018-10-18 16:30:41 +03:00
if !gjson.Valid(json) {
return errors.New("invalid json")
2017-09-30 04:10:12 +03:00
}
2018-10-18 16:30:41 +03:00
value := gjson.Get(json, "name.last")
2017-09-30 04:10:12 +03:00
```
2016-09-12 07:25:09 +03:00
## Unmarshal to a map
To unmarshal to a `map[string]interface{}` :
```go
m, ok := gjson.Parse(json).Value().(map[string]interface{})
2017-09-30 04:10:12 +03:00
if !ok {
2016-09-12 07:25:09 +03:00
// not a map
}
```
2016-12-12 20:33:28 +03:00
## Working with Bytes
If your JSON is contained in a `[]byte` slice, there's the [GetBytes ](https://godoc.org/github.com/tidwall/gjson#GetBytes ) function. This is preferred over `Get(string(data), path)` .
```go
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:
```go
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
2018-10-18 16:30:41 +03:00
The `GetMany` function can be used to get multiple values at the same time.
2016-12-12 20:33:28 +03:00
```go
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.
2016-09-12 07:25:09 +03:00
## Performance
Benchmarks of GJSON alongside [encoding/json ](https://golang.org/pkg/encoding/json/ ),
[ffjson ](https://github.com/pquerna/ffjson ),
[EasyJSON ](https://github.com/mailru/easyjson ),
2017-09-30 04:10:12 +03:00
[jsonparser ](https://github.com/buger/jsonparser ),
and [json-iterator ](https://github.com/json-iterator/go )
2016-09-12 07:25:09 +03:00
```
2017-09-30 04:10:12 +03:00
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
2016-09-12 07:25:09 +03:00
```
JSON document used:
```json
{
"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
```
2017-09-30 04:10:12 +03:00
*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 ](https://github.com/tidwall/gjson-benchmarks ).*
2016-09-12 07:25:09 +03:00
## Contact
Josh Baker [@tidwall ](http://twitter.com/tidwall )
## License
GJSON source code is available under the MIT [License ](/LICENSE ).