Skip to content

Instantly share code, notes, and snippets.

@eaigner
Created February 28, 2013 18:30
Show Gist options
  • Save eaigner/5058946 to your computer and use it in GitHub Desktop.
Save eaigner/5058946 to your computer and use it in GitHub Desktop.
Extract values from a map/array object using a key path, e.g. `a[0].b.c[1].d_e.f-g`
func ValueAtKeyPath(path string, v interface{}) interface{} {
// Parse the path syntax
p := make([]interface{}, 0, len(path))
rx := regexp.MustCompile(`([a-zA-Z0-9_\-]+)|(\[(\d+)\])`)
for _, m := range rx.FindAllStringSubmatch(path, -1) {
if strings.HasPrefix(m[0], "[") {
i, err := strconv.Atoi(m[len(m)-1])
if err != nil {
panic(err)
}
p = append(p, i)
} else {
p = append(p, m[0])
}
}
// Fetch the object at the parsed path
obj := v
for i, k := range p {
switch tk := k.(type) {
case int:
if o, ok := obj.([]interface{}); ok {
obj = o[tk]
} else {
panic(fmt.Sprintf("invalid array key at %d: %s", i, k))
}
case string:
if o, ok := obj.(map[string]interface{}); ok {
obj = o[tk]
} else {
panic(fmt.Sprintf("invalid object key at %d: %s", i, k))
}
}
}
return obj
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment