Allow missing keys in jsonpath

It is common in constrained circumstances to prefer an empty string
result from JSONPath templates for missing keys over an error. Several
other implementations provide this (the canonical JS and PHP, as well as
the Java implementation).  This also mirrors gotemplate, which allows
Options("missingkey=zero").

Added simple check and simple test case.
This commit is contained in:
Clayton Coleman
2016-08-30 12:50:51 -04:00
parent 1dfd6ab0c1
commit bcea2c8a4e
2 changed files with 24 additions and 6 deletions

View File

@@ -34,6 +34,8 @@ type JSONPath struct {
beginRange int
inRange int
endRange int
allowMissingKeys bool
}
func New(name string) *JSONPath {
@@ -45,6 +47,13 @@ func New(name string) *JSONPath {
}
}
// AllowMissingKeys allows a caller to specify whether they want an error if a field or map key
// cannot be located, or simply an empty result. The receiver is returned for chaining.
func (j *JSONPath) AllowMissingKeys(allow bool) *JSONPath {
j.allowMissingKeys = allow
return j
}
// Parse parse the given template, return error
func (j *JSONPath) Parse(text string) (err error) {
j.parser, err = Parse(j.name, text)
@@ -305,7 +314,7 @@ func (j *JSONPath) findFieldInValue(value *reflect.Value, node *FieldNode) (refl
return value.FieldByName(node.Value), nil
}
// evalField evaluates filed of struct or key of map.
// evalField evaluates field of struct or key of map.
func (j *JSONPath) evalField(input []reflect.Value, node *FieldNode) ([]reflect.Value, error) {
results := []reflect.Value{}
// If there's no input, there's no output
@@ -338,6 +347,9 @@ func (j *JSONPath) evalField(input []reflect.Value, node *FieldNode) ([]reflect.
}
}
if len(results) == 0 {
if j.allowMissingKeys {
return results, nil
}
return results, fmt.Errorf("%s is not found", node.Value)
}
return results, nil