ohler55/ojg

recursive descent on object, unexpected results

sschulz-t opened this issue · 7 comments

I am facing an issue with matching a json path with a recursive descent (e.g., $..city) against a go object.
See the following minimal example code (or use this go playground link: https://go.dev/play/p/mtIWc1-iNz3 )

package main
import (
	"fmt"
	"github.com/ohler55/ojg/jp"
)

func main() {
	type obj struct {
		Some string
		Data map[string]interface{}
	}

	o := obj{
		Some: "a_string",
		Data: map[string]interface{}{
			"test": map[string]interface{}{
				"city": "bielefeld",
			},
		},
	}

	path := "$..city"

	x, err := jp.ParseString(path)
	if err != nil {
		fmt.Println(err)
	}

	// this does not work
	fmt.Printf("(%s) GOT %v\n", path, x.Get(o))

	// however, this does
	fmt.Printf("(%s) GOT %v\n", path, x.Get(o.Data))
}

I expected x.Get(o) to resolve to the city as well. However, it does not.

Is this a bug or is it expected that it does not recurse into the struct's keys (e.g., o.Data) on its own?

Looks like a bug. I suspect it has something to do with the transition from reflection on the struct to the map data. I'll take a look and get it fixed.

It looks like the descent .. expression does not traverse struct fields. That will take a bit longer to implement but I will put it in the queue to be done.

Thanks for the quick response! As a temporary workaround, I marshal and unmarshal the object and feed jsonpath with that :)

Will the fixed descent use the struct key name or the json decorator (e.g., type obj struct { Some string json:"city" }) as well?

If there is a decorator it will be used otherwise the field name as lower case or what ever the options specify.

The struct-path has a fix. Still needs some testing but should work.

v1.20.0 released with the fix.

Can this be closed?