jmespath/go-jmespath

User-defined functions

Opened this issue ยท 12 comments

Could be great if one could extend default function list with their own functions.

https://github.com/jmespath/jmespath.py, already supports user defined functions - anyway it can be supported in this repo as well?

What's the use case for user-defined functions? The most important design decision of JMESPath is that all changes start with the spec and that it's language-agnostic. User defined functions deviate from both of these benefits.

There can be usecases where we need regex, client should allow the user to extend JMESpath if they wish. Also if its against design decision why is part of some of the clients such as the python client.

I've seen two benefits:

  • You're not using JMESPath for a language agnostic purpose, i.e writing some tool/CLI that uses JMESPath for something (maybe a config or something it exposes). In other words you don't need the language-agnostic part of jmespath.
  • You need functionality that likely will never be added to the JMESPath spec, Regex being a common one.

I've seen two benefits:

  • You're not using JMESPath for a language agnostic purpose, i.e writing some tool/CLI that uses JMESPath for something (maybe a config or something it exposes). In other words you don't need the language-agnostic part of jmespath.
  • You need functionality that likely will never be added to the JMESPath spec, Regex being a common one.

Exactly,
Hence we should allow the client to be extended to support user defined functions. The choice is simply left to the user.
Please share your thoughts on if we would be open to such a change in this client?

Regex is a use case that we are after as well.
Is there any way to easily incorporate it?

@mtdowling are you open to taking a PR to make it possible to add a custom function? Here is a test case for what I had in mind:

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

For others who may need this, here is my fork with the custom function support: https://github.com/kyverno/go-jmespath/.

Gotta say, this one baffled me, why we couldn't simply add a compare date function for ISO 8601 formatted strings due to the spec stating that > < etc are numerical only. This really limits our choices and forces us to do one of:

  • Add data to our schema in the right format, incurring additional marshaling and corrections on both ends
  • Look for some way to add a function, i.e. forking the project then having to maintain a fork
  • Moving to a different query language... we consider the sunk costs high
  • Using a different implementation (not really an option in go at the moment)
  • Using someone else's fork (thank you @JimBugwadia)

You can guess which option we chose.

For others who may need this, here is my fork with the custom function support: https://github.com/kyverno/go-jmespath/.

@JimBugwadia we at JMESPath Community would like to do just that: create a community around the language. To this end, we will need official maintainers of the various implementations. Would you like to take over the latest version and become official maintainer for the Go implementation? This version has most bug fixes from issues here and is up to standards with our spec. It "only" lacks third-party functions ๐Ÿ˜‰

Hi @springcomp I discussed this with my colleagues @eddycharly @realshuting @chipzoller and we are open to becoming the official maintainers of the Go implementation. @eddycharly has already created a draft PR for the custom functions support.

Hi @springcomp I discussed this with my colleagues @eddycharly @realshuting @chipzoller and we are open to becoming the official maintainers of the Go implementation. @eddycharly has already created a draft PR for the custom functions support.

Awesome, please, let me welcome you to JMESPath Community and give you access rights to the repository.