Get JSON values quickly - JSON parser for Go

GJSON
GoDoc GJSON Playground

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

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

Path Syntax

Below is a quick overview of the path syntax, for more complete information please check out GJSON 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, "nets": ["ig", "fb", "tw"]},
    {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
    {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
  ]
}
"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 % (like) and !% (not like) operators.

friends.#(last=="Murphy").first    >> "Dale"
friends.#(last=="Murphy")#.first   >> ["Dale","Jane"]
friends.#(age>45)#.last            >> ["Craig","Murphy"]
friends.#(first%"D*").last         >> "Murphy"
friends.#(first!%"D*").last        >> "Craig"
friends.#(nets.#(=="fb"))#.first   >> ["Dale","Roger"]

Please note that prior to v1.3.0, queries used the #[...] brackets. This was changed in v1.3.0 as to avoid confusion with the new multipath syntax. For backwards compatibility, #[...] will continue to work until the next major release.

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:

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

Modifiers and path chaining

New in version 1.2 is support for modifier functions and path chaining.

A modifier is a path component that performs custom processing on the json.

Multiple paths can be "chained" together using the pipe character. This is useful for getting results from a modified query.

For example, using the built-in @reverse modifier on the above json document, we'll get children array and reverse the order:

"children|@reverse"           >> ["Jack","Alex","Sara"]
"children|@reverse|0"         >> "Jack"

There are currently the following built-in modifiers:

  • @reverse: Reverse an array or the members of an object.
  • @ugly: Remove all whitespace from a json document.
  • @pretty: Make the json document more human readable.
  • @this: Returns the current element. It can be used to retrieve the root element.
  • @valid: Ensure the json document is valid.
  • @flatten: Flattens an array.
  • @join: Joins multiple objects into a single object.

Modifier arguments

A modifier may accept an optional argument. The argument can be a valid JSON document or just characters.

For example, the @pretty modifier takes a json object as its argument.

@pretty:{"sortKeys":true} 

Which makes the json pretty and orders all of its keys.

{
  "age":37,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer Hunter",
  "friends": [
    {"age": 44, "first": "Dale", "last": "Murphy"},
    {"age": 68, "first": "Roger", "last": "Craig"},
    {"age": 47, "first": "Jane", "last": "Murphy"}
  ],
  "name": {"first": "Tom", "last": "Anderson"}
}

The full list of @pretty options are sortKeys, indent, prefix, and width. Please see Pretty Options for more information.

Custom modifiers

You can also add custom modifiers.

For example, here we create a modifier that makes the entire json document upper or lower case.

gjson.AddModifier("case", func(json, arg string) string {
  if arg == "upper" {
    return strings.ToUpper(json)
  }
  if arg == "lower" {
    return strings.ToLower(json)
  }
  return json
})
"children|@case:upper"           >> ["SARA","ALEX","JACK"]
"children|@case:lower|@reverse"  >> ["jack","alex","sara"]

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

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 through 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 found here.

Contact

Josh Baker @tidwall

License

GJSON source code is available under the MIT License.

Comments
  • Why does memory occupy more and more

    Why does memory occupy more and more

    Function location : github.com/tidwall/gjson.fromBytesGet

    image

    7 minutes later

    image

    Automatic restart until the physical machine is full of memory

    code

    for {
    	data, err := client.Get(url)
    	if err != nil {
    		log.DetailError(err)
    	}
    	RefreshL2Cache(data)
    	time.Sleep(interval * time.Second)
    }
    
    func RefreshL2Cache(data []byte) {
    	e.l2lock.Lock()
    	e.l2cache = gjson.GetBytes(data, "data.list")
    	e.l2lock.Unlock()
    }
    
    
  • Why not use int, uint, float  as  return type of Int(), Uint(), Float()

    Why not use int, uint, float as return type of Int(), Uint(), Float()

            Redis = redis.NewClient(&redis.Options{
                Addr:     Config.Get("redis.default.host").String(),
                Password: Config.Get("redis.default.password").String(),
                DB:       int(Config.Get("redis.default.database").Int()),
            })
    

    when i use .Int() metod, also need to use int()

  • Help writing complex queries

    Help writing complex queries

    Hi @tidwall!

    I'm struggling to write some more complex queries using gjson. Using your json example in http://tidwall.com/gjson-play/:

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

    How can I write a query to get the friends.#.age when last is Murphy and first is Dale? I tried something like friends.#[last=="Murphy" && first=="Dale"]#.age without success.

    Also, how can I write a query to get same field when last name is Murphy or Craig? I tried something like friends.#[last=="Murphy" || last=="Craig"]#.age without success either.

    I'm writing in the hopes I could get some light on how to do it or, in the case it's not supported, to update the documentation accordingly.

    Thanks, Gleidson

  • Exists() condition seems erroneous

    Exists() condition seems erroneous

    The code for Exists is:

    func (t Result) Exists() bool {
    	return t.Type != Null || len(t.Raw) != 0
    }
    

    But it seems to me this should read:

    func (t Result) Exists() bool {
    	return t.Type != Null && len(t.Raw) != 0
    }
    

    why specify Type != Null if the second clause overrules it always?

    With a null value here, you get Exists() == true.

  • query key == value

    query key == value

    Great work here!

    I really like the query syntax as it allows moving the logic into definitions! Given:

    {
      "sub":"xyz",
      "children": ["Sara","Alex","Jack"]
    }
    

    I can nicely test a match of an array: children.#(%"Alex")

    However, if I like to test a match for an object I would expect this to work sub=="xyz" which doesn't.

    I really cannot add code / condition checking in my function because it would make this library obsolete Thank you for suggestion!

  • Parsing of large integer ids is broken: integers should remain integers

    Parsing of large integer ids is broken: integers should remain integers

    Hi,

    Thanks for making this great library available!

    There is a flaw when parsing large integer ids. It's common in REST APIs to use large integer ids for entity ids - often they encode time info in them, and they have nothing to do with an RDB autoincrement sequence.

    In this case, gsjon is parsing those JSON integers into float64, and the precision of the id is being lost, rendering it useless. JSON integers should be parsed into int64 not float64. I know that the default go json package also parses all numbers into float64, but that also feels wrong to me. JSON says nothing about numerical types only that they could be integers or floats, and JSON parsing in most other languages like Ruby, Objective-C, etc., will choose the correct numerical type in the language based on the observed type of the literal (e.g. 6.2 would be a float but 6 would be an integer) and the type of the field's values can vary from one record to another: the same field could be a float from a literal of 6.2 but an integer from a float of 6.

    Here's an example in go using gjson:

    jsonString := `{"IdentityData":{"GameInstanceId":634866135153775564}}`
    value := gjson.Get(jsonString, "IdentityData.GameInstanceId")
    
    // gjson has stored value as float64 and any use of it seems to produce
    // 634866135153775616.0, which is the wrong id and
    // even gjson.GetBytes([]byte(jsonString), "IdentityData.GameInstanceId")) prints as
    // a float64 634866135153775616.0
    
    // This seems to be the only way to get the correct id
    gameInstanceIdString := gjson.Get(jsonString, "IdentityData.GameInstanceId").Raw
    gameInstanceId, errGameInstanceId := strconv.ParseInt(gameInstanceIdString, 10, 64)
    if errGameInstanceId != nil {
      // We can use gameInstanceId and it will be the correct value of 634866135153775564
    }
    

    That is pretty cumbersome just to get an integer id out of some json. I love gjson - it's well-designed and a breeze to use, but having to do all this just to preserve the true value of an integer id makes gjson a lot less compelling.

    Am I missing something here? Is there an easier way to do this?

    If this was some kind of large measurement or something, I guess the imprecision/rounding wouldn't be as big a deal. But this is an id, and 634866135153775616 is not useful when we really need the true value 634866135153775564.

    Any help would be hugely appreciated!

  • How to query JSON including literal field/values in the output?

    How to query JSON including literal field/values in the output?

    I'm building a JSON transformation feature using GJSON and the use case is to parse an input and generate a transformed JSON, but also including extra fields (i.e. fields/values not present in the source JSON). Is that possible with GJSON? Example:

    Given the following input (from GJSON playground):

    {
      "name": {"first": "Tom", "last": "Anderson"}
    }
    

    When the input is {name.last,"foo":name.first}, the result is {"last":"Anderson","foo":"Tom"}

    But when the input is {name.last,"foo":"bar"}, the result is: {"last":"Anderson"}

    I expected that the result would be {"last":"Anderson","foo":"bar"}

    Is there any way to achieve that?

  • Creates a constant for maximum and minimum JSON Integers and documents them

    Creates a constant for maximum and minimum JSON Integers and documents them

    Creates constants for maximum and minimum safe Integers in JSON and documents them as per:

    • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER
    • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER
  • Set Index property for contained Results when loading object properties into a GoLang map

    Set Index property for contained Results when loading object properties into a GoLang map

    Summary

    This PR will ensure the ContainedResult.Index property is assigned the sequential order when TopLevelResults.Map() is run.

    Example Code

    The JSON code used would look like this:

    {
      "stack": {
        "webserver": "nginx:1.14.0",
        "processvm": "php:7.1.18",
        "dbserver": "mysql:5.5.60",
        "webproxy": "proxy:1.14.0"
      }
    }
    

    And then the Go code that uses the Index might look like this:

    type Component struct {
    	Index int
    	Name  string
    }
    type ComponentMap map[string]*Component
    func (p *Project) GetStack() ComponentMap {
    	r:= gjson.GetBytes(p.json,"stack" )
    	rm:= r.Map()
    	cm := ComponentMap{}
    	for t,v:= range rm {
    		cm[t] = &Component{
    			Index: v.Index,
    			Name:  v.String(),
    		}
    	}
    	return cm
    }
    

    Background

    I was using encoding/json and ran into the problem that the properties of JSON objects loaded would be reordered and I had no way to maintain their original order if I was modifying them and then writing them back out. I am using JSON for a configuration file that will probably be hand-modified at times, and feel it would be a very bad UX if my CLI app reordered object properties every time we updated the file.

    So I found gjson which seems incredible -- kudos! -- but unfortunately it seems to have the same problem. Then I noticed the Result.Index property and was hopeful that it would allow me to capture the original order, but unfortunately it turns out that gjson was actually not setting the Result.Index property when I needed it.

    Upon further digging it appeared that it would be easy to fix Result.arrayOrMap() to assign .Index where needed, which is what I did and hence this pull request.

    Note that I am a new Go programmer so I may not have handled it correctly but I certainly hope so because I would really prefer to use your official version rather than my forked version.

    Thank You!

    Thanks in advance for considering this PR.

  • Struct tags to help marshall directly into struct objects

    Struct tags to help marshall directly into struct objects

    Hey @tidwall

    I think it would be great if we could have struct tags which will help unmarshall the string directly into a given struct.

    type A struct { B string gjson:"data.id" }

    Lemme know your thoughts on it

  • Add support to return multiple indexes when multiple matches are found

    Add support to return multiple indexes when multiple matches are found

    This pull request adds a new field to the Result structure that will contain multiple indexes when multiple matches are found. Currently only a single index is provided that is set to 0 when you provide a query to gather multiple matches (a query to access multiple child paths "friends.#.first" or to find all matches #(...)#). I called the new field HashtagIndexes because I believe this should only apply when a query uses a hashtag (but definitely open to any other name suggestions).

    I am working on a project that would benefit from knowing all the indexes, I added a unit test called TestHashtagIndexesMatchesRaw that is very similar to what I would like to do with this feature. Basically run two separate queries and walk over the results of one and use the indexes to find matches. Thank you for looking over this pull request! Hopefully this is the right approach to achieve this.

  • Update the documentation of custom modifiers to specify the need of quotes in return type

    Update the documentation of custom modifiers to specify the need of quotes in return type

    Can we update the documentation of custom modifiers, to clearly specify that return type string should have quotes. If it doesn't have quotes we get empty value as result

    package main
    
    import (
    	"strings"
    
    	"github.com/tidwall/gjson"
    )
    
    const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
    
    func main() {
    	gjson.AddModifier("case", func(json, arg string) string {
    		if arg == "upper" {
    			return strings.ToUpper(json)
    		}
    		if arg == "lower" {
    			return strings.ToLower(json)
    		}
    		return json
    	})
    	gjson.AddModifier("age", func(json, arg string) string {
    		if arg == "0" {
                            // Quotes is necessary here
    			return `"test"`
    		}
    		return json
    	})
    
    	value2 := gjson.Get(json, "name.last|@case:upper")
    	println(value2.String())
    	value := gjson.Get(json, "name.last|@age:0")
    	println(value.String())
    }
    
    

    I am thinking of adding this as note below custom modifier doc section

    Please note that returned string type should have double quotes in it. 
    	gjson.AddModifier("age", func(json, arg string) string {
    		if arg == "custom-arg" {
                            // Quotes is necessary here
    			return `"test"`
    		}
    		return json
    	})
    
  • Get first N values from an array as single result

    Get first N values from an array as single result

    Hello, currently trying to figure out how to return a limited number of elements from an array as a single result, without just resorting to path.to.array.[0,1,2,...,n].

    The most "elegant" way I've been able to figure out is:

    limit := 1000
    
    var i int
    var results []json.RawMessage
    result.Get("path.to.array").ForEach(func(_, value gjson.Result) bool {
       results = append(results, json.RawMessage(value.Raw))
       i++
       return i < limit
    })
    
    raw, _ := json.Marshal(results)
    return gjson.ParseBytes(raw)
    

    Is there a simpler/more efficient way of doing this, maybe akin to path.to.array.[0:n]?

  • result.Paths(json string) does not return paths when used more than one #'s

    result.Paths(json string) does not return paths when used more than one #'s

    Hi, amazing work 👍

    I have the following json:

    {
      "people": [
        {"name": "John", "addresses": [{"zip": 123}]}
      ]
    }
    

    When I try to access the name property inside people, result.Paths() returns a slice of strings containing the path like this:

    result := gjson.Get(string(json), field)
    fmt.Println(result.Paths(string(json)))
    

    people.#.name [people.0.name]

    However when I do the same for the zip inside the addresses array,

    people.#.addresses.#.zip

    the result.Paths() no longer returns a slice of strings.

    Is this a known limitation? If so, is there a workaround for this?

  • Can I add a default value without a key?

    Can I add a default value without a key?

    {
        "name": {
            "first": "Tom",
            "last": "Anderson"
        },
        "age": 37,
        "children": [
            "Sara",
            "Alex",
            "Jack"
        ],
        "fav.movie": "Deer Hunter",
        "friends": [
            {
                "first": "Dale",
                "last": "Murphy",
                "age": 44,
                "nets": [
                    "ig",
                    "fb",
                    "tw"
                ],
                "others": [
                    {
                        "k": "v",
                        "v": "k"
                    },
                    {
                        "k": "v",
                        "v": "k"
                    }
                ]
            },
            {
                "last": "Craig",
                "age": 68,
                "nets": [
                    "fb",
                    "tw"
                ],
                "others": [
                    {
                        "v": "k"
                    },
                    {
                        "k": "v",
                        "v": "k"
                    }
                ]
            },
            {
                "first": "Jane",
                "last": "Murphy",
                "age": 47,
                "nets": [
                    "ig",
                    "tw"
                ],
                "others": [
                    {
                        "k": "v",
                        "v": "k"
                    },
                    {
                        "v": "k"
                    }
                ]
            }
        ]
    }
    

    Current results:

    "friends.#.first"    >> ["Dale", "Jane"]
    "friends.#.others.#.k"  >> [["v", "v"], ["v"],["v"]]
    

    With default value:

    "friends.#.first"    >> ["Dale", nil, "Jane"]
    "friends.#.others.#.k"  >> [["v", "v"], [nil, "v"],["v", nil]]
    

    Thanks:)

  • Iteration over arrays in combination with @this and nested # not working as expected

    Iteration over arrays in combination with @this and nested # not working as expected

    While playing around with the library, I tried looping over arrays combined with @this.

    The libary does seem to detect whether or not the given path is valid (#.#.#.@this does not work at all as expected) but does not return the expected results. As in the example below, I expected the same results for both loops. Am I missing something here?

    Using 0.#.@this works just fine.

    https://go.dev/play/p/VKc4RFPEvAL

    package main
    
    import (
    	"fmt"
    
    	"github.com/tidwall/gjson"
    )
    
    const json1 = `
    	[{ "a": "b1", "b": "c1", "c": "d1"},
    	{ "a": "b2", "b": "c2", "c": "d2"},
    	{ "a": "b3", "b": "c3", "c": "d3"},
    	{ "a": "b4", "b": "c4", "c": "d4"},
    	{"foo":"bar"}]
    `
    const json2 = `[ 
    	[{ "a": "b1", "b": "c1", "c": "d1"},
    	{ "a": "b2", "b": "c2", "c": "d2"},
    	{ "a": "b3", "b": "c3", "c": "d3"},
    	{ "a": "b4", "b": "c4", "c": "d4"}], 
    	[{"foo":"bar"}]
    ]`
    
    func main() {
    	result := gjson.Get(json1, "#.@this")
    	result.ForEach(func(key, value gjson.Result) bool {
    		fmt.Println(value)
    		return true // keep iterating
    	})
    	fmt.Println("---")
    	result = gjson.Get(json2, "#.#.@this")
    	result.ForEach(func(key, value gjson.Result) bool {
    		fmt.Println(value)
    		return true // keep iterating
    	})
    }
    

    Output:

    { "a": "b1", "b": "c1", "c": "d1"}
    { "a": "b2", "b": "c2", "c": "d2"}
    { "a": "b3", "b": "c3", "c": "d3"}
    { "a": "b4", "b": "c4", "c": "d4"}
    {"foo":"bar"}
    ---
    [{ "a": "b1", "b": "c1", "c": "d1"},{ "a": "b2", "b": "c2", "c": "d2"},{ "a": "b3", "b": "c3", "c": "d3"},{ "a": "b4", "b": "c4", "c": "d4"}]
    [{"foo":"bar"}]
    
Fast JSON parser and validator for Go. No custom structs, no code generation, no reflection

fastjson - fast JSON parser and validator for Go Features Fast. As usual, up to 15x faster than the standard encoding/json. See benchmarks. Parses arb

Jan 5, 2023
A JSON stream parser for Go

pjson A JSON stream parser for Go Example The example below prints all string values from a JSON document. package

Oct 3, 2022
One of the fastest alternative JSON parser for Go that does not require schema

Alternative JSON parser for Go (10x times faster standard library) It does not require you to know the structure of the payload (eg. create structs),

Jan 2, 2023
A fast json parser for go

rjson rjson is a json parser that relies on Ragel-generated state machines for most parsing. rjson's api is minimal and focussed on efficient parsing.

Sep 26, 2022
Slow and unreliable JSON parser generator (in progress)

VivaceJSON Fast and reliable JSON parser generator Todo List parse fields parse types generate struct generate (keypath+key) to struct Value Mapping F

Nov 26, 2022
JSON:API compatible query string parser

QParser The package helps to parse part of the URL path and its parameters string to a handy structure. The structure format is compatible with the JS

Dec 21, 2021
Easy JSON parser for Go. No custom structs, no code generation, no reflection

Easy JSON parser for Go. No custom structs, no code generation, no reflection

Dec 28, 2022
A JSON parser/generator for Go

FASTJSON fastjson是java版本的fastjson库的api做一个翻译,方便习惯java的人操作json数据 主要适用场景:层级和字段都不能确定的json 这个库并不实现高性能json解析,依赖标准库json 这个库并没有100%实现java版的api 安装 go get -u gi

Dec 29, 2021
Get the value in JSON by path, no need for struct

Get the value in JSON by path, no need for struct

Dec 6, 2021
Simple Email Parser

mp - mail parser mp is a simple cli email parser. It currently takes stdin and outputs JSON. Example: cat fixtures/test.eml | mp { "Text": "Hello w

Sep 26, 2022
Go-json5 - A parser that supports a subset of the JSON5 specification

barney.ci/go-json5 This library implements a parser that supports a subset of th

Oct 10, 2022
JSON diff library for Go based on RFC6902 (JSON Patch)

jsondiff jsondiff is a Go package for computing the diff between two JSON documents as a series of RFC6902 (JSON Patch) operations, which is particula

Dec 4, 2022
Fast JSON encoder/decoder compatible with encoding/json for Go
Fast JSON encoder/decoder compatible with encoding/json for Go

Fast JSON encoder/decoder compatible with encoding/json for Go

Jan 6, 2023
Package json implements encoding and decoding of JSON as defined in RFC 7159

Package json implements encoding and decoding of JSON as defined in RFC 7159. The mapping between JSON and Go values is described in the documentation for the Marshal and Unmarshal functions

Jun 26, 2022
Json-go - CLI to convert JSON to go and vice versa
Json-go - CLI to convert JSON to go and vice versa

Json To Go Struct CLI Install Go version 1.17 go install github.com/samit22/js

Jul 29, 2022
JSON Spanner - A Go package that provides a fast and simple way to filter or transform a json document

JSON SPANNER JSON Spanner is a Go package that provides a fast and simple way to

Sep 14, 2022
Abstract JSON for golang with JSONPath support

Abstract JSON Abstract JSON is a small golang package provides a parser for JSON with support of JSONPath, in case when you are not sure in its struct

Jan 5, 2023
Small utility to create JSON objects
Small utility to create JSON objects

gjo Small utility to create JSON objects. This was inspired by jpmens/jo. Support OS Mac Linux Windows Requirements Go 1.1.14~ Git Installtion Build $

Dec 8, 2022
A Go package for handling common HTTP JSON responses.

go-respond A Go package for handling common HTTP JSON responses. Installation go get github.com/nicklaw5/go-respond Usage The goal of go-respond is to

Sep 26, 2022