README.md
1<p align="center">
2<img
3 src="logo.png"
4 width="240" height="78" border="0" alt="GJSON">
5<br>
6<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>
7<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>
8<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>
9</p>
10
11
12
13<p align="center">get json values quickly</a></p>
14
15GJSON is a Go package that provides a [fast](#performance) and [simple](#get-a-value) way to get values from a json document.
16It 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).
17
18Also check out [SJSON](https://github.com/tidwall/sjson) for modifying json, and the [JJ](https://github.com/tidwall/jj) command line tool.
19
20Getting Started
21===============
22
23## Installing
24
25To start using GJSON, install Go and run `go get`:
26
27```sh
28$ go get -u github.com/tidwall/gjson
29```
30
31This will retrieve the library.
32
33## Get a value
34Get 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.
35
36```go
37package main
38
39import "github.com/tidwall/gjson"
40
41const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
42
43func main() {
44 value := gjson.Get(json, "name.last")
45 println(value.String())
46}
47```
48
49This will print:
50
51```
52Prichard
53```
54*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.*
55
56## Path Syntax
57
58Below is a quick overview of the path syntax, for more complete information please
59check out [GJSON Syntax](SYNTAX.md).
60
61A path is a series of keys separated by a dot.
62A key may contain special wildcard characters '\*' and '?'.
63To access an array value use the index as the key.
64To get the number of elements in an array or to access a child path, use the '#' character.
65The dot and wildcard characters can be escaped with '\\'.
66
67```json
68{
69 "name": {"first": "Tom", "last": "Anderson"},
70 "age":37,
71 "children": ["Sara","Alex","Jack"],
72 "fav.movie": "Deer Hunter",
73 "friends": [
74 {"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
75 {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
76 {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
77 ]
78}
79```
80```
81"name.last" >> "Anderson"
82"age" >> 37
83"children" >> ["Sara","Alex","Jack"]
84"children.#" >> 3
85"children.1" >> "Alex"
86"child*.2" >> "Jack"
87"c?ildren.0" >> "Sara"
88"fav\.movie" >> "Deer Hunter"
89"friends.#.first" >> ["Dale","Roger","Jane"]
90"friends.1.last" >> "Craig"
91```
92
93You can also query an array for the first match by using `#(...)`, or find all
94matches with `#(...)#`. Queries support the `==`, `!=`, `<`, `<=`, `>`, `>=`
95comparison operators and the simple pattern matching `%` (like) and `!%`
96(not like) operators.
97
98```
99friends.#(last=="Murphy").first >> "Dale"
100friends.#(last=="Murphy")#.first >> ["Dale","Jane"]
101friends.#(age>45)#.last >> ["Craig","Murphy"]
102friends.#(first%"D*").last >> "Murphy"
103friends.#(first!%"D*").last >> "Craig"
104friends.#(nets.#(=="fb"))#.first >> ["Dale","Roger"]
105```
106
107*Please note that prior to v1.3.0, queries used the `#[...]` brackets. This was
108changed in v1.3.0 as to avoid confusion with the new
109[multipath](SYNTAX.md#multipaths) syntax. For backwards compatibility,
110`#[...]` will continue to work until the next major release.*
111
112## Result Type
113
114GJSON supports the json types `string`, `number`, `bool`, and `null`.
115Arrays and Objects are returned as their raw json types.
116
117The `Result` type holds one of these:
118
119```
120bool, for JSON booleans
121float64, for JSON numbers
122string, for JSON string literals
123nil, for JSON null
124```
125
126To directly access the value:
127
128```go
129result.Type // can be String, Number, True, False, Null, or JSON
130result.Str // holds the string
131result.Num // holds the float64 number
132result.Raw // holds the raw json
133result.Index // index of raw value in original json, zero means index unknown
134```
135
136There are a variety of handy functions that work on a result:
137
138```go
139result.Exists() bool
140result.Value() interface{}
141result.Int() int64
142result.Uint() uint64
143result.Float() float64
144result.String() string
145result.Bool() bool
146result.Time() time.Time
147result.Array() []gjson.Result
148result.Map() map[string]gjson.Result
149result.Get(path string) Result
150result.ForEach(iterator func(key, value Result) bool)
151result.Less(token Result, caseSensitive bool) bool
152```
153
154The `result.Value()` function returns an `interface{}` which requires type assertion and is one of the following Go types:
155
156The `result.Array()` function returns back an array of values.
157If the result represents a non-existent value, then an empty array will be returned.
158If the result is not a JSON array, the return value will be an array containing one result.
159
160```go
161boolean >> bool
162number >> float64
163string >> string
164null >> nil
165array >> []interface{}
166object >> map[string]interface{}
167```
168
169### 64-bit integers
170
171The `result.Int()` and `result.Uint()` calls are capable of reading all 64 bits, allowing for large JSON integers.
172
173```go
174result.Int() int64 // -9223372036854775808 to 9223372036854775807
175result.Uint() int64 // 0 to 18446744073709551615
176```
177
178## Modifiers and path chaining
179
180New in version 1.2 is support for modifier functions and path chaining.
181
182A modifier is a path component that performs custom processing on the
183json.
184
185Multiple paths can be "chained" together using the pipe character.
186This is useful for getting results from a modified query.
187
188For example, using the built-in `@reverse` modifier on the above json document,
189we'll get `children` array and reverse the order:
190
191```
192"children|@reverse" >> ["Jack","Alex","Sara"]
193"children|@reverse|0" >> "Jack"
194```
195
196There are currently the following built-in modifiers:
197
198- `@reverse`: Reverse an array or the members of an object.
199- `@ugly`: Remove all whitespace from a json document.
200- `@pretty`: Make the json document more human readable.
201- `@this`: Returns the current element. It can be used to retrieve the root element.
202- `@valid`: Ensure the json document is valid.
203- `@flatten`: Flattens an array.
204- `@join`: Joins multiple objects into a single object.
205
206### Modifier arguments
207
208A modifier may accept an optional argument. The argument can be a valid JSON
209document or just characters.
210
211For example, the `@pretty` modifier takes a json object as its argument.
212
213```
214@pretty:{"sortKeys":true}
215```
216
217Which makes the json pretty and orders all of its keys.
218
219```json
220{
221 "age":37,
222 "children": ["Sara","Alex","Jack"],
223 "fav.movie": "Deer Hunter",
224 "friends": [
225 {"age": 44, "first": "Dale", "last": "Murphy"},
226 {"age": 68, "first": "Roger", "last": "Craig"},
227 {"age": 47, "first": "Jane", "last": "Murphy"}
228 ],
229 "name": {"first": "Tom", "last": "Anderson"}
230}
231```
232
233*The full list of `@pretty` options are `sortKeys`, `indent`, `prefix`, and `width`.
234Please see [Pretty Options](https://github.com/tidwall/pretty#customized-output) for more information.*
235
236### Custom modifiers
237
238You can also add custom modifiers.
239
240For example, here we create a modifier that makes the entire json document upper
241or lower case.
242
243```go
244gjson.AddModifier("case", func(json, arg string) string {
245 if arg == "upper" {
246 return strings.ToUpper(json)
247 }
248 if arg == "lower" {
249 return strings.ToLower(json)
250 }
251 return json
252})
253```
254
255```
256"children|@case:upper" >> ["SARA","ALEX","JACK"]
257"children|@case:lower|@reverse" >> ["jack","alex","sara"]
258```
259
260## JSON Lines
261
262There's support for [JSON Lines](http://jsonlines.org/) using the `..` prefix, which treats a multilined document as an array.
263
264For example:
265
266```
267{"name": "Gilbert", "age": 61}
268{"name": "Alexa", "age": 34}
269{"name": "May", "age": 57}
270{"name": "Deloise", "age": 44}
271```
272
273```
274..# >> 4
275..1 >> {"name": "Alexa", "age": 34}
276..3 >> {"name": "Deloise", "age": 44}
277..#.name >> ["Gilbert","Alexa","May","Deloise"]
278..#(name="May").age >> 57
279```
280
281The `ForEachLines` function will iterate through JSON lines.
282
283```go
284gjson.ForEachLine(json, func(line gjson.Result) bool{
285 println(line.String())
286 return true
287})
288```
289
290## Get nested array values
291
292Suppose you want all the last names from the following json:
293
294```json
295{
296 "programmers": [
297 {
298 "firstName": "Janet",
299 "lastName": "McLaughlin",
300 }, {
301 "firstName": "Elliotte",
302 "lastName": "Hunter",
303 }, {
304 "firstName": "Jason",
305 "lastName": "Harold",
306 }
307 ]
308}
309```
310
311You would use the path "programmers.#.lastName" like such:
312
313```go
314result := gjson.Get(json, "programmers.#.lastName")
315for _, name := range result.Array() {
316 println(name.String())
317}
318```
319
320You can also query an object inside an array:
321
322```go
323name := gjson.Get(json, `programmers.#(lastName="Hunter").firstName`)
324println(name.String()) // prints "Elliotte"
325```
326
327## Iterate through an object or array
328
329The `ForEach` function allows for quickly iterating through an object or array.
330The key and value are passed to the iterator function for objects.
331Only the value is passed for arrays.
332Returning `false` from an iterator will stop iteration.
333
334```go
335result := gjson.Get(json, "programmers")
336result.ForEach(func(key, value gjson.Result) bool {
337 println(value.String())
338 return true // keep iterating
339})
340```
341
342## Simple Parse and Get
343
344There's a `Parse(json)` function that will do a simple parse, and `result.Get(path)` that will search a result.
345
346For example, all of these will return the same result:
347
348```go
349gjson.Parse(json).Get("name").Get("last")
350gjson.Get(json, "name").Get("last")
351gjson.Get(json, "name.last")
352```
353
354## Check for the existence of a value
355
356Sometimes you just want to know if a value exists.
357
358```go
359value := gjson.Get(json, "name.last")
360if !value.Exists() {
361 println("no last name")
362} else {
363 println(value.String())
364}
365
366// Or as one step
367if gjson.Get(json, "name.last").Exists() {
368 println("has a last name")
369}
370```
371
372## Validate JSON
373
374The `Get*` and `Parse*` functions expects that the json is well-formed. Bad json will not panic, but it may return back unexpected results.
375
376If you are consuming JSON from an unpredictable source then you may want to validate prior to using GJSON.
377
378```go
379if !gjson.Valid(json) {
380 return errors.New("invalid json")
381}
382value := gjson.Get(json, "name.last")
383```
384
385## Unmarshal to a map
386
387To unmarshal to a `map[string]interface{}`:
388
389```go
390m, ok := gjson.Parse(json).Value().(map[string]interface{})
391if !ok {
392 // not a map
393}
394```
395
396## Working with Bytes
397
398If 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)`.
399
400```go
401var json []byte = ...
402result := gjson.GetBytes(json, path)
403```
404
405If 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:
406
407```go
408var json []byte = ...
409result := gjson.GetBytes(json, path)
410var raw []byte
411if result.Index > 0 {
412 raw = json[result.Index:result.Index+len(result.Raw)]
413} else {
414 raw = []byte(result.Raw)
415}
416```
417
418This 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`.
419
420## Get multiple values at once
421
422The `GetMany` function can be used to get multiple values at the same time.
423
424```go
425results := gjson.GetMany(json, "name.first", "name.last", "age")
426```
427
428The return value is a `[]Result`, which will always contain exactly the same number of items as the input paths.
429
430## Performance
431
432Benchmarks of GJSON alongside [encoding/json](https://golang.org/pkg/encoding/json/),
433[ffjson](https://github.com/pquerna/ffjson),
434[EasyJSON](https://github.com/mailru/easyjson),
435[jsonparser](https://github.com/buger/jsonparser),
436and [json-iterator](https://github.com/json-iterator/go)
437
438```
439BenchmarkGJSONGet-8 3000000 372 ns/op 0 B/op 0 allocs/op
440BenchmarkGJSONUnmarshalMap-8 900000 4154 ns/op 1920 B/op 26 allocs/op
441BenchmarkJSONUnmarshalMap-8 600000 9019 ns/op 3048 B/op 69 allocs/op
442BenchmarkJSONDecoder-8 300000 14120 ns/op 4224 B/op 184 allocs/op
443BenchmarkFFJSONLexer-8 1500000 3111 ns/op 896 B/op 8 allocs/op
444BenchmarkEasyJSONLexer-8 3000000 887 ns/op 613 B/op 6 allocs/op
445BenchmarkJSONParserGet-8 3000000 499 ns/op 21 B/op 0 allocs/op
446BenchmarkJSONIterator-8 3000000 812 ns/op 544 B/op 9 allocs/op
447```
448
449JSON document used:
450
451```json
452{
453 "widget": {
454 "debug": "on",
455 "window": {
456 "title": "Sample Konfabulator Widget",
457 "name": "main_window",
458 "width": 500,
459 "height": 500
460 },
461 "image": {
462 "src": "Images/Sun.png",
463 "hOffset": 250,
464 "vOffset": 250,
465 "alignment": "center"
466 },
467 "text": {
468 "data": "Click Here",
469 "size": 36,
470 "style": "bold",
471 "vOffset": 100,
472 "alignment": "center",
473 "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
474 }
475 }
476}
477```
478
479Each operation was rotated though one of the following search paths:
480
481```
482widget.window.name
483widget.image.hOffset
484widget.text.onMouseUp
485```
486
487*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).*
488
489
490## Contact
491Josh Baker [@tidwall](http://twitter.com/tidwall)
492
493## License
494
495GJSON source code is available under the MIT [License](/LICENSE).
496