hashicorp/go-bexpr

Panic on using map[string]interface{}

akamensky opened this issue · 4 comments

I am trying to use this library for evaluation of user provided expressions. Which means that there are no defined structs for objects. Instead it is a parsed JSON, (which simply outputs map[string]interface{}). However, this library seems unable to handle such use case? Or am I using it wrong way?

Example code:

func main() {
	userjson := `{"id": 123}`

	filejson := `{"owner": 123}`

	var User map[string]interface{}
	var File map[string]interface{}

	err := fastjson.Unmarshal([]byte(userjson), &User)
	if err != nil {
		panic(err)
	}

	err = fastjson.Unmarshal([]byte(filejson), &File)
	if err != nil {
		panic(err)
	}

	type Env map[string]interface{}

	e := map[string]interface{}{
		"file": File,
		"user": User,
	}

	expr := "file.owner == user.id"

	eval, err := bexpr.CreateEvaluatorForType(expr, nil, (*map[string]interface{})(nil))
	if err != nil {
		panic(err)
	}

	result, err := eval.Evaluate(e)
	if err != nil {
		panic(err)
	}

	fmt.Println(result)
}

@akamensky This library is really intended for filtering outputs of structured data at the moment.

Internally we generate potential selectable fields from the data type not the datas value. So in the case of map[string]interface{} we end up with no selectable fields as we have no way of knowing what might be behind that interface{}.

Currently evaluation ensures that only those fields that we know about from during the introspection of the data type are used and only those operations that we know should be allowed based on the original data are used. In fact we take a preliminary pass and validating all fields used in an expression with the field configuration prior to evaluating anything.

While we could potentially allow for more lazy expression validation during evaluation its not something that fits into the core use cases behind creating this library (which really was to have the ability to filter API outputs rather than inputs. For now at least your best bet is probably to use an alternative library. https://github.com/antonmedv/expr is one which I have seen and is geared towards more general use cases I believe.

Enhancement:

• Allow for lazy field selector validation through interface{} types.

For now at least your best bet is probably to use an alternative library. https://github.com/antonmedv/expr is one which I have seen and is geared towards more general use cases I believe.

I already looked at https://github.com/antonmedv/expr, but while it can do exactly just that, it does not restrict expressions to boolean only, and in my use case I need exactly only boolean expressions and not allow any other types to be returned. From the expression syntax perspective this library would fit my needs best.

Thanks anyway for your response, looks like I would have to stick with expr for now.