|
|
@ -4,6 +4,8 @@ import (
|
|
|
|
"encoding/json"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"reflect"
|
|
|
|
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type Doc struct {
|
|
|
|
type Doc struct {
|
|
|
@ -19,9 +21,12 @@ func (d *Doc) Get(path string, dest interface{}) error {
|
|
|
|
return fmt.Errorf("no item found at path %s (doc is empty)", path)
|
|
|
|
return fmt.Errorf("no item found at path %s (doc is empty)", path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
v, ok := d.items[path]
|
|
|
|
var v interface{}
|
|
|
|
if !ok {
|
|
|
|
parts := strings.Split(path, "/")
|
|
|
|
return fmt.Errorf("no item found at path %s", path)
|
|
|
|
|
|
|
|
|
|
|
|
v, err := seekValue(path, parts, d.items)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dt := reflect.TypeOf(dest)
|
|
|
|
dt := reflect.TypeOf(dest)
|
|
|
@ -34,3 +39,41 @@ func (d *Doc) Get(path string, dest interface{}) error {
|
|
|
|
dve.Set(reflect.ValueOf(v))
|
|
|
|
dve.Set(reflect.ValueOf(v))
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func seekValue(fullpath string, parts []string, root interface{}) (interface{}, error) {
|
|
|
|
|
|
|
|
if len(parts) == 0 {
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("path is empty")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
head, tail := parts[0], parts[1:]
|
|
|
|
|
|
|
|
n, err := strconv.Atoi(head)
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
|
|
|
|
l, ok := root.([]interface{})
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("can only index a []interface{}, root is %s", reflect.TypeOf(root))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if n >= len(l) {
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("path %s is out of bounds, can't get the %d index from a slice of len %d", fullpath, n, len(l))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
v := l[n]
|
|
|
|
|
|
|
|
if len(tail) == 0 {
|
|
|
|
|
|
|
|
return v, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return seekValue(fullpath, tail, v)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m, ok := root.(map[string]interface{})
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("can only key a map[string]interface{}, root is %v", reflect.TypeOf(root))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
v, ok := m[head]
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("unable to seek value at path %s: no value found for part %s", fullpath, head)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(tail) == 0 {
|
|
|
|
|
|
|
|
return v, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return seekValue(fullpath, tail, v)
|
|
|
|
|
|
|
|
}
|
|
|
|