Allow nil values to be returned by AllSettings

Signed-off-by: Bogdan Drutu <bogdandrutu@gmail.com>
This commit is contained in:
Bogdan Drutu 2020-09-18 10:08:05 -07:00
parent d9d7dcdc63
commit dcd7fbbff7
No known key found for this signature in database
GPG key ID: 44D691C6C11748F1
2 changed files with 42 additions and 3 deletions

View file

@ -199,6 +199,7 @@ type Viper struct {
automaticEnvApplied bool automaticEnvApplied bool
envKeyReplacer StringReplacer envKeyReplacer StringReplacer
allowEmptyEnv bool allowEmptyEnv bool
allowNilValues bool
config map[string]interface{} config map[string]interface{}
override map[string]interface{} override map[string]interface{}
@ -257,6 +258,14 @@ func KeyDelimiter(d string) Option {
}) })
} }
// AllowNilValues tells Viper to not ignore keys with nil values.
// For backward compatibility reasons this is false by default.
func AllowNilValues(allowNilValues bool) Option {
return optionFunc(func(v *Viper) {
v.allowNilValues = allowNilValues
})
}
// StringReplacer applies a set of replacements to a string. // StringReplacer applies a set of replacements to a string.
type StringReplacer interface { type StringReplacer interface {
// Replace returns a copy of s with all replacements performed. // Replace returns a copy of s with all replacements performed.
@ -1960,9 +1969,8 @@ func (v *Viper) AllSettings() map[string]interface{} {
// start from the list of keys, and construct the map one value at a time // start from the list of keys, and construct the map one value at a time
for _, k := range v.AllKeys() { for _, k := range v.AllKeys() {
value := v.Get(k) value := v.Get(k)
if value == nil { // Default behavior is to not allow nil values, but users can enable this via config.
// should not happen, since AllKeys() returns only keys holding a value, if value == nil && !v.allowNilValues {
// check just in case anything changes
continue continue
} }
path := strings.Split(k, v.keyDelim) path := strings.Split(k, v.keyDelim)

View file

@ -2258,6 +2258,37 @@ func TestKeyDelimiter(t *testing.T) {
assert.Equal(t, expected, actual) assert.Equal(t, expected, actual)
} }
var yamlExampleWithNilValues = []byte(`Hacker: true
name: steve
hobbies:
clothing:
jacket:
`)
func TestNilValues(t *testing.T) {
vNil := NewWithOptions(AllowNilValues(true))
vNil.SetConfigType("yaml")
require.NoError(t, vNil.ReadConfig(strings.NewReader(string(yamlExampleWithNilValues))))
expectedNil := map[string]interface{}{
"hacker": true,
"name": "steve",
"hobbies": nil,
"clothing": map[string]interface{}{
"jacket": nil,
},
}
assert.EqualValues(t, expectedNil, vNil.AllSettings())
vNotNil := NewWithOptions(AllowNilValues(false))
vNotNil.SetConfigType("yaml")
require.NoError(t, vNotNil.ReadConfig(strings.NewReader(string(yamlExampleWithNilValues))))
expectedNotNil := map[string]interface{}{
"hacker": true,
"name": "steve",
}
assert.EqualValues(t, expectedNotNil, vNotNil.AllSettings())
}
func BenchmarkGetBool(b *testing.B) { func BenchmarkGetBool(b *testing.B) {
key := "BenchmarkGetBool" key := "BenchmarkGetBool"
v = New() v = New()