Add IsExplicit function to check for non-default.

The IsSet function returns true even if the value that's available comes
from the default. Rather than changing the behavior of IsSet, adding a
new IsExplicit function allows checking for non-default values without
breaking existing behavior. This is intended to address issue #276 among
other things.
This commit is contained in:
Joe Frank 2018-08-01 13:51:20 -06:00
parent d493c32b69
commit 829e890a30
2 changed files with 32 additions and 3 deletions

View file

@ -612,7 +612,7 @@ func GetViper() *Viper {
func Get(key string) interface{} { return v.Get(key) } func Get(key string) interface{} { return v.Get(key) }
func (v *Viper) Get(key string) interface{} { func (v *Viper) Get(key string) interface{} {
lcaseKey := strings.ToLower(key) lcaseKey := strings.ToLower(key)
val := v.find(lcaseKey) val := v.find(lcaseKey, true)
if val == nil { if val == nil {
return nil return nil
} }
@ -887,7 +887,7 @@ func (v *Viper) BindEnv(input ...string) error {
// flag, env, config file, key/value store, default. // flag, env, config file, key/value store, default.
// Viper will check to see if an alias exists first. // Viper will check to see if an alias exists first.
// Note: this assumes a lower-cased key given. // Note: this assumes a lower-cased key given.
func (v *Viper) find(lcaseKey string) interface{} { func (v *Viper) find(lcaseKey string, useDefault bool) interface{} {
var ( var (
val interface{} val interface{}
@ -975,6 +975,11 @@ func (v *Viper) find(lcaseKey string) interface{} {
return nil return nil
} }
// Only use default values if asked
if !useDefault {
return nil
}
// Default next // Default next
val = v.searchMap(v.defaults, path) val = v.searchMap(v.defaults, path)
if val != nil { if val != nil {
@ -1020,7 +1025,16 @@ func readAsCSV(val string) ([]string, error) {
func IsSet(key string) bool { return v.IsSet(key) } func IsSet(key string) bool { return v.IsSet(key) }
func (v *Viper) IsSet(key string) bool { func (v *Viper) IsSet(key string) bool {
lcaseKey := strings.ToLower(key) lcaseKey := strings.ToLower(key)
val := v.find(lcaseKey) val := v.find(lcaseKey, true)
return val != nil
}
// IsExplicit checks to see if the key has a non-default value set.
// IsExplicit is case-insensitive for a key.
func IsExplicit(key string) bool { return v.IsExplicit(key) }
func (v *Viper) IsExplicit(key string) bool {
lcaseKey := strings.ToLower(key)
val := v.find(lcaseKey, false)
return val != nil return val != nil
} }

View file

@ -766,6 +766,21 @@ func TestIsSet(t *testing.T) {
assert.False(t, v.IsSet("helloworld")) assert.False(t, v.IsSet("helloworld"))
v.Set("helloworld", "fubar") v.Set("helloworld", "fubar")
assert.True(t, v.IsSet("helloworld")) assert.True(t, v.IsSet("helloworld"))
v.SetDefault("default", "value")
assert.True(t, v.IsSet("default"))
}
func TestIsExplicit(t *testing.T) {
v := New()
v.SetConfigType("yaml")
v.ReadConfig(bytes.NewBuffer(yamlExample))
assert.True(t, v.IsExplicit("clothing.jacket"))
assert.False(t, v.IsExplicit("clothing.jackets"))
assert.False(t, v.IsExplicit("helloworld"))
v.Set("helloworld", "fubar")
assert.True(t, v.IsExplicit("helloworld"))
v.SetDefault("default", "value")
assert.False(t, v.IsExplicit("default"))
} }
func TestDirsSearch(t *testing.T) { func TestDirsSearch(t *testing.T) {