mirror of
https://github.com/spf13/viper
synced 2025-05-07 04:37:20 +00:00
feat: auto bind environment variables in viper.Unmarshal
This commit is contained in:
parent
c4dcd31f68
commit
049cf065a8
2 changed files with 52 additions and 0 deletions
21
viper.go
21
viper.go
|
@ -1111,9 +1111,30 @@ func Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
|
|||
}
|
||||
|
||||
func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
|
||||
err := v.autoBindEnvs(rawVal)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not auto bind environment variables: %w", err)
|
||||
}
|
||||
|
||||
return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
|
||||
}
|
||||
|
||||
func (v *Viper) autoBindEnvs(rawVal any) error {
|
||||
envKeys := map[string]any{}
|
||||
if err := mapstructure.Decode(rawVal, &envKeys); err != nil {
|
||||
return fmt.Errorf("could not decode mapstructure: %w", err)
|
||||
}
|
||||
|
||||
structKeys := v.flattenAndMergeMap(map[string]bool{}, envKeys, "")
|
||||
for key, _ := range structKeys {
|
||||
if err := v.BindEnv(key); err != nil {
|
||||
return fmt.Errorf(`could not bind env "%s": %w`, key, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// defaultDecoderConfig returns default mapstructure.DecoderConfig with support
|
||||
// of time.Duration values & string slices.
|
||||
func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
|
||||
|
|
|
@ -914,6 +914,37 @@ func TestUnmarshal(t *testing.T) {
|
|||
)
|
||||
}
|
||||
|
||||
func TestUnmarshalWithEnvs(t *testing.T) {
|
||||
type config struct {
|
||||
Port int
|
||||
Host string
|
||||
Nested struct {
|
||||
Value string
|
||||
AnotherValue string
|
||||
RenamedValue string `mapstructure:"another"`
|
||||
}
|
||||
}
|
||||
|
||||
t.Setenv("CONFIG_PORT", "8080")
|
||||
t.Setenv("CONFIG_HOST", "http://localhost")
|
||||
t.Setenv("CONFIG_NESTED_VALUE", "baz")
|
||||
t.Setenv("CONFIG_NESTED_ANOTHER", "value")
|
||||
|
||||
v := New()
|
||||
v.SetEnvPrefix("CONFIG")
|
||||
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||
|
||||
configObject := config{}
|
||||
err := v.Unmarshal(&configObject)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 8080, configObject.Port)
|
||||
assert.Equal(t, "http://localhost", configObject.Host)
|
||||
assert.Equal(t, "baz", configObject.Nested.Value)
|
||||
assert.Empty(t, configObject.Nested.AnotherValue)
|
||||
assert.Equal(t, "value", configObject.Nested.RenamedValue)
|
||||
}
|
||||
|
||||
func TestUnmarshalWithDecoderOptions(t *testing.T) {
|
||||
Set("credentials", "{\"foo\":\"bar\"}")
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue