Skip to content

Commit

Permalink
Support maps in configuration structure
Browse files Browse the repository at this point in the history
  • Loading branch information
celian-garcia authored and iamolegga committed Aug 4, 2020
1 parent 33dffdb commit 64431f6
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type bazzy struct {
type config struct {
Foo string
Barry barry
Barries map[string]barry
Bazzy bazzy `mapstructure:",squash"`
}

Expand All @@ -50,16 +51,23 @@ type config struct {
// Barry:
// bar: 42
// Baz: true
// Barries:
// key1:
// Bar: 255
// key2:
// Bar: 256
//
// And then it could be overriden by next env variables:
// FOO=foo
// BARRY_BAR=42
// BAZ=true
// BARRIES_KEY1_BAR=42
//
// Or with prefix:
// MYAPP_FOO=foo
// MYAPP_BARRY_BAR=42
// MYAPP_BAZ=true
// MYAPP_BARRIES_KEY1_BAR=42

func main() {
var c config
Expand Down
10 changes: 10 additions & 0 deletions enviper.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ func (e *Enviper) Unmarshal(rawVal interface{}) error {
return err
}
}
// We need to unmarshal before the env binding to make sure that keys of maps are bound just like the struct fields
// We silence errors here because we'll unmarshal a second time
_ = e.Viper.Unmarshal(rawVal)
e.readEnvs(rawVal)
return e.Viper.Unmarshal(rawVal)
}
Expand Down Expand Up @@ -84,6 +87,13 @@ func (e *Enviper) bindEnvs(in interface{}, prev ...string) {
switch fv.Kind() {
case reflect.Struct:
e.bindEnvs(fv.Interface(), append(prev, tv)...)
case reflect.Map:
iter := fv.MapRange()
for iter.Next() {
if key, ok := iter.Key().Interface().(string); ok {
e.bindEnvs(iter.Value().Interface(), append(prev, tv, key)...)
}
}
default:
env := strings.Join(append(prev, tv), ".")
// Viper.BindEnv will never return error
Expand Down
5 changes: 5 additions & 0 deletions enviper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ func (s *UnmarshalSuite) TestWithEnvs() {
s.Equal("fooooo", c.Foo)
s.Equal(2, c.Bar.BAZ)
s.Equal(false, c.QUX.Quuux)
s.Equal(true, c.QuxMap["key1"].Quuux)
s.Equal(false, c.QuxMap["key2"].Quuux)

s.tearDownEnvConfig()
}
Expand Down Expand Up @@ -139,6 +141,9 @@ type Config struct {
Bar struct {
BAZ int `mapstructure:"baz"`
} `mapstructure:"bar"`
QuxMap map[string]struct {
Quuux bool
}
QUX `mapstructure:",squash"`
}

Expand Down
5 changes: 5 additions & 0 deletions fixture.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
Foo: foo
bar:
baz: 1
QuxMap:
key1:
Quuux: false
key2:
Quuux: false
Quuux: true
1 change: 1 addition & 0 deletions fixture_env
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
PREF_FOO=fooooo
PREF_BAR_BAZ=2
PREF_QUUUX=false
PREF_QUXMAP_KEY1_QUUUX=true

0 comments on commit 64431f6

Please sign in to comment.