mirror of
https://github.com/spf13/viper
synced 2025-05-06 20:27:17 +00:00
Merge 68a8b52d7b
into 8dc2790b02
This commit is contained in:
commit
97befb3142
1 changed files with 56 additions and 1 deletions
57
viper.go
57
viper.go
|
@ -29,6 +29,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -512,6 +513,56 @@ func (v *Viper) searchMapWithPathPrefixes(source map[string]interface{}, path []
|
|||
return nil
|
||||
}
|
||||
|
||||
func (v *Viper) searchMapWithArrayPrefix(source map[string]interface{}, path []string) interface{} {
|
||||
if len(path) == 0 {
|
||||
return source
|
||||
}
|
||||
|
||||
next, ok := source[path[0]]
|
||||
if ok {
|
||||
// Immediate Key Value
|
||||
if len(path) == 1 {
|
||||
return next
|
||||
}
|
||||
|
||||
// Value from Nested key
|
||||
switch next.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
return v.searchMapWithArrayPrefix(cast.ToStringMap(next), path[1:])
|
||||
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
|
||||
return v.searchMapWithArrayPrefix(next.(map[string]interface{}), path[1:])
|
||||
case []interface{}:
|
||||
v1 := cast.ToSlice(next)
|
||||
for k2, v2 := range v1 {
|
||||
if reflect.TypeOf(v2).Kind() == reflect.Map {
|
||||
if _, err := strconv.ParseInt(path[1], 10, 64); err == nil {
|
||||
if strconv.Itoa(k2) == path[1] {
|
||||
return v.searchMapWithArrayPrefix(cast.ToStringMap(v2), path[1:])
|
||||
}
|
||||
} else {
|
||||
return v.searchMapWithArrayPrefix(cast.ToStringMap(v2), path[1:])
|
||||
}
|
||||
} else {
|
||||
if _, err := strconv.ParseInt(path[1], 10, 64); err == nil {
|
||||
if strconv.Itoa(k2) == path[1] {
|
||||
return v2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
if _, err := strconv.ParseInt(path[0], 10, 64); err == nil {
|
||||
return v.searchMapWithArrayPrefix(source, path[1:])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// isPathShadowedInDeepMap makes sure the given path is not shadowed somewhere
|
||||
// on its path in the map.
|
||||
// e.g., if "foo.bar" has a value in the given map, it “shadows”
|
||||
|
@ -882,7 +933,6 @@ func (v *Viper) BindEnv(input ...string) error {
|
|||
// Viper will check to see if an alias exists first.
|
||||
// Note: this assumes a lower-cased key given.
|
||||
func (v *Viper) find(lcaseKey string) interface{} {
|
||||
|
||||
var (
|
||||
val interface{}
|
||||
exists bool
|
||||
|
@ -956,6 +1006,11 @@ func (v *Viper) find(lcaseKey string) interface{} {
|
|||
if val != nil {
|
||||
return val
|
||||
}
|
||||
val = v.searchMapWithArrayPrefix(v.config, path)
|
||||
if val != nil {
|
||||
return val
|
||||
}
|
||||
|
||||
if nested && v.isPathShadowedInDeepMap(path, v.config) != "" {
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue