Code Monkey home page Code Monkey logo

go-jmespath's Introduction

go-jmespath - A JMESPath implementation in Go

NOTE: This is a fork of go-jmespath with custom function support. See issue #29.

Build Status

go-jmespath is a GO implementation of JMESPath, which is a query language for JSON. It will take a JSON document and transform it into another JSON document through a JMESPath expression.

Using go-jmespath is really easy. There's a single function you use, jmespath.search:

> import "github.com/kyverno/go-jmespath"
>
> var jsondata = []byte(`{"foo": {"bar": {"baz": [0, 1, 2, 3, 4]}}}`) // your data
> var data interface{}
> err := json.Unmarshal(jsondata, &data)
> result, err := jmespath.Search("foo.bar.baz[2]", data)
result = 2

In the example we gave the search function input data of {"foo": {"bar": {"baz": [0, 1, 2, 3, 4]}}} as well as the JMESPath expression foo.bar.baz[2], and the search function evaluated the expression against the input data to produce the result 2.

The JMESPath language can do a lot more than select an element from a list. Here are a few more examples:

> var jsondata = []byte(`{"foo": {"bar": {"baz": [0, 1, 2, 3, 4]}}}`) // your data
> var data interface{}
> err := json.Unmarshal(jsondata, &data)
> result, err := jmespath.search("foo.bar", data)
result = { "baz": [ 0, 1, 2, 3, 4 ] }


> var jsondata  = []byte(`{"foo": [{"first": "a", "last": "b"},
                           {"first": "c", "last": "d"}]}`) // your data
> var data interface{}
> err := json.Unmarshal(jsondata, &data)
> result, err := jmespath.search({"foo[*].first", data)
result [ 'a', 'c' ]


> var jsondata = []byte(`{"foo": [{"age": 20}, {"age": 25},
                           {"age": 30}, {"age": 35},
                           {"age": 40}]}`) // your data
> var data interface{}
> err := json.Unmarshal(jsondata, &data)
> result, err := jmespath.search("foo[?age > `30`]")
result = [ { age: 35 }, { age: 40 } ]

You can also pre-compile your query. This is usefull if you are going to run multiple searches with it:

	> var jsondata = []byte(`{"foo": "bar"}`)
	> var data interface{}
    > err := json.Unmarshal(jsondata, &data)
	> precompiled, err := Compile("foo")
	> if err != nil{
    >   // ... handle the error
    > }
    > result, err := precompiled.Search(data)
	result = "bar"

Adding Custom Functions

Adding custom functions is only supported for compiled patterns. See test case as an example:

func TestCustomFunction(t *testing.T) {
	assert := assert.New(t)
	data := make(map[string]interface{})
	data["foo"] = "BAR"
	precompiled, err := Compile("to_lower(foo)")
	precompiled.Register(&FunctionEntry{
		Name: "to_lower",
		Arguments: []ArgSpec{
			{Types: []JpType{JpString}},
		},
		Handler: func (arguments []interface{}) (interface{}, error) {
			s := arguments[0].(string)
			return strings.ToLower(s), nil
		},
	})

	assert.Nil(err)
	result, err := precompiled.Search(data)
	assert.Nil(err)
	assert.Equal("bar", result)
}

More Resources

The example above only show a small amount of what a JMESPath expression can do. If you want to take a tour of the language, the best place to go is the JMESPath Tutorial.

One of the best things about JMESPath is that it is implemented in many different programming languages including python, ruby, php, lua, etc. To see a complete list of libraries, check out the JMESPath libraries page.

And finally, the full JMESPath specification can be found on the JMESPath site.

go-jmespath's People

Contributors

adamkorcz avatar ajorg-aws avatar brianbland avatar eddycharly avatar ejholmes avatar eparis avatar highlyunavailable avatar jamesls avatar jasdel avatar jimbugwadia avatar kacejot avatar khaledemaradev avatar realshuting avatar reedobrien avatar samj1912 avatar shawnps avatar shawnps-sigsci avatar xibz avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

go-jmespath's Issues

Go modules

Perhaps you can move the master branch's go.mod file from

module github.com/jmespath/go-jmespath

to

module github.com/kyverno/go-jmespath

Which would allow users to use you're fork directly?

Function `contains` crashes for element of type object

Problem

With the following JMESPatch expression (download):

contains(`[{"k": "v"}]`, `{ "k": "v" }`)

go-jmespath panicks:

$ kyverno jp -e contains.jmespath.txt <<<"{}"
panic: runtime error: comparing uncomparable type map[string]interface {}

goroutine 1 [running]:
github.com/jmespath/go-jmespath.jpfContains({0xc000bd08e0?, 0xc000bd08e0?, 0x2?})
	/home/runner/go/pkg/mod/github.com/kyverno/[email protected]/functions.go:455 +0x145
github.com/jmespath/go-jmespath.(*functionCaller).CallFunction(0x28a9be0?, {0xc000796240, 0x8}, {0xc000bd08e0, 0x2, 0x2}, 0xc000bde0b0)
	/home/runner/go/pkg/mod/github.com/kyverno/[email protected]/functions.go:401 +0x252
github.com/jmespath/go-jmespath.(*treeInterpreter).Execute(0xc000bde0b0, {0x4, {0x27e9160, 0xc000bcc280}, {0xc000bca420, 0x2, 0x2}}, {0x290c1c0, 0xc000bd2720})
	/home/runner/go/pkg/mod/github.com/kyverno/[email protected]/interpreter.go:93 +0x1fe9
github.com/jmespath/go-jmespath.(*JMESPath).Search(...)
	/home/runner/go/pkg/mod/github.com/kyverno/[email protected]/api.go:37
github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/jp.Command.func1(0xc000bc8c00?, {0xc000bd03e0?, 0x2?, 0x2?})
	/home/runner/work/kyverno/kyverno/cmd/cli/kubectl-kyverno/jp/jp_command.go:87 +0x846
github.com/spf13/cobra.(*Command).execute(0xc000bc8c00, {0xc000bd03c0, 0x2, 0x2})
	/home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:916 +0x862
github.com/spf13/cobra.(*Command).ExecuteC(0xc000bc8000)
	/home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:1040 +0x3b4
github.com/spf13/cobra.(*Command).Execute(...)
	/home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:968
main.main()
	/home/runner/work/kyverno/kyverno/cmd/cli/kubectl-kyverno/main.go:35 +0xc9

Expected Behavior

The expression should evaluate to true.

Interestingly, a comparison using == of the same object values works as expected (download):

`{"k":"v"}` == `{ "k": "v" }`
$ kyverno jp -e equals.jmespath.txt <<<"{}"
true

Additional Info

Kyverno versions known to be affected (non-exhaustive): 1.8.1, 1.8.3

Reuse interpreter across multiple searches

The API current allows Compile which compiles a query and creates a new treeInterpreter.

This works well for short lived programs, but can add significant overhead for long running programs that compile and execute thousands of queries, especially when custom functions need to be loaded when the interpreter is initialized. Profiling showed that around 75% of time spent in a query was for initializing the interpreter.

For such use cases, it would be optimal to create a single Interpreter and reuse it across invocations.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.