Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion builtin/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package builtin

import (
"fmt"
"github.com/expr-lang/expr/environment"
"math"
"reflect"
"strconv"
Expand Down Expand Up @@ -421,7 +422,7 @@ func get(params ...any) (out any, err error) {
fieldName := i.(string)
value := v.FieldByNameFunc(func(name string) bool {
field, _ := v.Type().FieldByName(name)
switch field.Tag.Get("expr") {
switch field.Tag.Get(environment.GetGoTag()) {
case "-":
return false
case fieldName:
Expand Down
3 changes: 2 additions & 1 deletion checker/nature/utils.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package nature

import (
"github.com/expr-lang/expr/environment"
"reflect"

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

func fieldName(field reflect.StructField) (string, bool) {
switch taggedName := field.Tag.Get("expr"); taggedName {
switch taggedName := field.Tag.Get(environment.GetGoTag()); taggedName {
case "-":
return "", false
case "":
Expand Down
16 changes: 16 additions & 0 deletions environment/environment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package environment

import "os"

const (
ExprEnvGotag = "expr__gotag"
DefaultGotag = "expr"
)

func GetGoTag() string {
if v := os.Getenv(ExprEnvGotag); v != "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to specify this from env?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to set gotag in config like expr.Compile("", expr.WithGotag("json")), but there is some expr usage that cannot reach the config value, like in lib.go. Even in where we can reach the config value, it feels code intrusive to pass the value all the way down there. So i picked env since it is easy to read.

expr/builtin/lib.go

Lines 420 to 432 in 1c09e5e

case reflect.Struct:
fieldName := i.(string)
value := v.FieldByNameFunc(func(name string) bool {
field, _ := v.Type().FieldByName(name)
switch field.Tag.Get("expr") {
case "-":
return false
case fieldName:
return true
default:
return name == fieldName
}
})

return v
} else {
return DefaultGotag
}
}
49 changes: 49 additions & 0 deletions expr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2890,3 +2890,52 @@ func TestIssue807(t *testing.T) {
t.Fatalf("expected 'in' operator to return false for unexported field")
}
}

func TestJsonGoTag(t *testing.T) {
type Embed struct {
Field string `json:"jsonField"`
}

type MyStruct struct {
Field string `json:"jsonField"`
Embed Embed `json:"embedField"`
}

type EmbedNoTag struct {
Field string
}

type MyStructNoTag struct {
Field string
Embed EmbedNoTag
}

env := map[string]any{
"obj": MyStruct{Field: "value", Embed: Embed{Field: "embedFieldValue"}},
"objNoTag": MyStructNoTag{Field: "value", Embed: EmbedNoTag{Field: "embedFieldValue"}},
}

if err := os.Setenv("expr__gotag", "json"); err != nil {
t.Fatalf("error setting env var: %v", err)
}
defer os.Unsetenv("expr__gotag")

code := `
{
"fieldValue": obj.jsonField,
"embedFieldValue": obj.embedField.jsonField,
"fieldValueNoTag": objNoTag.Field,
"embedFieldValueNoTag": objNoTag.Embed.Field
}
`
prog, err := expr.Compile(code, expr.Env(env))
require.NoError(t, err)

out, err := expr.Run(prog, env)
require.NoError(t, err)
require.NotNil(t, out)
require.Equal(t, "value", out.(map[string]any)["fieldValue"])
require.Equal(t, "value", out.(map[string]any)["fieldValueNoTag"])
require.Equal(t, "embedFieldValue", out.(map[string]any)["embedFieldValue"])
require.Equal(t, "embedFieldValue", out.(map[string]any)["embedFieldValueNoTag"])
}
5 changes: 3 additions & 2 deletions vm/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package runtime

import (
"fmt"
"github.com/expr-lang/expr/environment"
"math"
"reflect"

Expand Down Expand Up @@ -65,7 +66,7 @@ func Fetch(from, i any) any {
fieldName := i.(string)
value := v.FieldByNameFunc(func(name string) bool {
field, _ := v.Type().FieldByName(name)
switch field.Tag.Get("expr") {
switch field.Tag.Get(environment.GetGoTag()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better not introduce another configuration surface and use same conf pgk.

case "-":
return false
case fieldName:
Expand Down Expand Up @@ -223,7 +224,7 @@ func In(needle any, array any) bool {
panic(fmt.Sprintf("cannot use %T as field name of %T", needle, array))
}
field, ok := v.Type().FieldByName(n.String())
if !ok || !field.IsExported() || field.Tag.Get("expr") == "-" {
if !ok || !field.IsExported() || field.Tag.Get(environment.GetGoTag()) == "-" {
return false
}
value := v.FieldByIndex(field.Index)
Expand Down