Created
February 28, 2013 18:30
-
-
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`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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