mirror of
https://github.com/spf13/viper
synced 2025-05-07 04:37:20 +00:00
Added support for parsing keys with index notation (eg.: "prop[0].sub-prop")
This commit is contained in:
parent
907c19d40d
commit
02aa8552a1
1 changed files with 26 additions and 2 deletions
28
viper.go
28
viper.go
|
@ -29,6 +29,8 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -480,6 +482,8 @@ func (v *Viper) searchMap(source map[string]interface{}, path []string) interfac
|
|||
return nil
|
||||
}
|
||||
|
||||
var prefixIndexRE = regexp.MustCompile(`^([^\[]+)(?:\[(\d+)\])?$`)
|
||||
|
||||
// searchMapWithPathPrefixes recursively searches for a value for path in source map.
|
||||
//
|
||||
// While searchMap() considers each path element as a single map key, this
|
||||
|
@ -500,6 +504,12 @@ func (v *Viper) searchMapWithPathPrefixes(source map[string]interface{}, path []
|
|||
for i := len(path); i > 0; i-- {
|
||||
prefixKey := strings.ToLower(strings.Join(path[0:i], v.keyDelim))
|
||||
|
||||
prefixIndex := prefixIndexRE.ReplaceAllString(prefixKey, "$2")
|
||||
if prefixIndex != "" {
|
||||
// remove the index from the key
|
||||
prefixKey = prefixIndexRE.ReplaceAllString(prefixKey, "$1")
|
||||
}
|
||||
|
||||
next, ok := source[prefixKey]
|
||||
if ok {
|
||||
// Fast path
|
||||
|
@ -509,13 +519,27 @@ func (v *Viper) searchMapWithPathPrefixes(source map[string]interface{}, path []
|
|||
|
||||
// Nested case
|
||||
var val interface{}
|
||||
switch next.(type) {
|
||||
switch n := next.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
val = v.searchMapWithPathPrefixes(cast.ToStringMap(next), path[i:])
|
||||
case map[string]interface{}:
|
||||
// Type assertion is safe here since it is only reached
|
||||
// if the type of `next` is the same as the type being asserted
|
||||
val = v.searchMapWithPathPrefixes(next.(map[string]interface{}), path[i:])
|
||||
val = v.searchMapWithPathPrefixes(n, path[i:])
|
||||
case []interface{}:
|
||||
if prefixIndex != "" {
|
||||
index, err := strconv.Atoi(prefixIndex)
|
||||
if err == nil {
|
||||
item := n[index]
|
||||
|
||||
switch nextItem := item.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
val = v.searchMapWithPathPrefixes(cast.ToStringMap(nextItem), path[i:])
|
||||
case map[string]interface{}:
|
||||
val = v.searchMapWithPathPrefixes(nextItem, path[i:])
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
// got a value but nested key expected, do nothing and look for next prefix
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue