Skip to content

feat: Add nil-safety for fetching fields#959

Open
sonalys wants to merge 1 commit into
expr-lang:masterfrom
sonalys:nil-safe-fetch
Open

feat: Add nil-safety for fetching fields#959
sonalys wants to merge 1 commit into
expr-lang:masterfrom
sonalys:nil-safe-fetch

Conversation

@sonalys
Copy link
Copy Markdown

@sonalys sonalys commented May 14, 2026

Summary

Allow fetching undefined/nil fields, by using expr.NilSafe().
Example:

package main

import (
	"encoding/json"
	"fmt"

	"github.com/expr-lang/expr"
)

func main() {
	got := any(nil)

	remapProgram := `
	let activeItems = filter(cart, .active == true);
	{
		testMap:     map(nonExistent.field, .attr),
		testFilter:  filter(nonExistent.field, .attr == "value"),
		testConcatUndefined: "Value: " + string(nonExistent.field),
		testGT: (nonExistent.field ?? 0) > 500,
	}
	`

	program, err := expr.Compile(remapProgram,
		expr.NilSafe(),
	)
	if err != nil {
		panic(err)
	}

	output, err := expr.Run(program, got)
	if err != nil {
		panic(err)
	}

	finalJSON, _ := json.MarshalIndent(output, "", "  ")
	fmt.Println(string(finalJSON))
}

// Output:
// {
//   "testConcatUndefined": "Value: \u003cnil\u003e",
//   "testFilter": [],
//   "testGT": false,
//   "testMap": []
// }

Details

  • Modify runtime.Fetch to use sentinel instead of panic
  • Ensure OpBegin works with type nil for reflect.Value.Len
  • Improve performance with early return for nil value in builtin.lib.go.get
  • Add expr.NilSafe() configuration

Open Questions

  • Maybe expr.AllowUndefinedVariables() would be a better fit for the configuration
  • I'm not sure how to properly test the implemented functionality, I kindly ask for feedback

Issues: #434

- Return nil instead of panic on runtime.Fetch
- Ensure OpBegin works with type nil for reflect.Value.Len
- Improve perf on early return for nil from in builtin.lib.go.get
- Add expr.NilSafe() configuration
@sonalys sonalys changed the title feat: Add nil-safety to runtime.Fetch feat: Add nil-safety for fetching fields May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant