-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rewrite Accessor to fix array access issues, also add a Delete method #142
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR. It looks generally fine, but I'm quite concerned about the extensive use of reflection and its affect on performance.
@hanzei thoughts?
if nextObj.Kind() == reflect.Interface { | ||
nextObj = nextObj.Elem() | ||
} | ||
// fmt.Printf("key: %s %v\n", key, nextObj.Kind()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// fmt.Printf("key: %s %v\n", key, nextObj.Kind()) |
key := path[index] | ||
arrayIndex := getArrayIndex(key) | ||
var nextObj reflect.Value | ||
// fmt.Printf("current: %s %v\n", key, currentObj.Kind()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// fmt.Printf("current: %s %v\n", key, currentObj.Kind()) |
if nextArrayIndex >= 0 { | ||
// next element will be an array | ||
if !nextObj.IsValid() || nextObj.Kind() != reflect.Slice { | ||
// fmt.Printf("new slice for %s\n", key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// fmt.Printf("new slice for %s\n", key) |
// fmt.Printf("new slice for %s\n", key) | ||
newObj = reflect.ValueOf(make([]interface{}, nextArrayIndex+1, max(nextArrayIndex+1, 8))) | ||
} else if nextObj.Len() <= nextArrayIndex { | ||
// fmt.Printf("nextObj %s len %d cap %d\n", key, nextObj.Len(), nextObj.Cap()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// fmt.Printf("nextObj %s len %d cap %d\n", key, nextObj.Len(), nextObj.Cap()) |
break | ||
// next element will be an normal object | ||
if !nextObj.IsValid() || nextObj.Kind() != reflect.Map { | ||
// fmt.Printf("new map for %s\n", key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// fmt.Printf("new map for %s\n", key) |
return current | ||
} | ||
if newObj != nextObj || (value != nil && index == lastIndex) { | ||
// fmt.Printf("assign key %s to %v\n", key, newObj) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// fmt.Printf("assign key %s to %v\n", key, newObj) |
// arrayAccessRegexString is the regex used to extract the array number | ||
// from the access path | ||
arrayAccessRegexString = `^(.+)\[([0-9]+)\]$` | ||
type notFoundError struct{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why don't we just make this
var NotFoundError = errors.New("not found")
idx, err := strconv.ParseUint(key[1:len(key)-1], 10, 64) | ||
if err != nil { | ||
// should not happen, otherwise the path is invalid | ||
panic(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would still rather not panic and instead return error here.
@Niels-Be Would you be open on writing benchmarks tests for the affected code to measure the performance impact? |
Summary
This is a rewrite of the accessor code to fix a lot of issues with access to arrays.
I added some tests that were failing bevor this rewrite.
There should be no breaking changes with this code.
However the new code could allow errors to be forwarded to the caller.
e.g. for Get() to differentiate between not found and json null value.
Or to notify the caller about an invalid path expression.
Maybe add new methods for this?
In this PR all errors are just swallowed to keep compatibility.
Additionally a new Delete method (as requested in #141) is introduced which was trivial to add with the new code.
Checklist
task test
task lint