mirror of
https://github.com/spf13/viper
synced 2024-12-23 03:57:01 +00:00
handle int slice as well
This commit is contained in:
parent
aa2861e085
commit
7e17080926
2 changed files with 30 additions and 23 deletions
45
viper.go
45
viper.go
|
@ -1149,19 +1149,11 @@ func unmarshalPostProcess(input any, opts ...DecoderConfigOption) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
v.postProcessingSliceFields(map[string]bool{}, structKeyMap, "")
|
v.postProcessingSliceFields(structKeyMap, "")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO remove shadow
|
func (v *Viper) postProcessingSliceFields(m map[string]any, prefix string) {
|
||||||
func (v *Viper) postProcessingSliceFields(shadow map[string]bool, m map[string]any, prefix string) map[string]bool {
|
|
||||||
if shadow != nil && prefix != "" && shadow[prefix] {
|
|
||||||
// prefix is shadowed => nothing more to flatten
|
|
||||||
return shadow
|
|
||||||
}
|
|
||||||
if shadow == nil {
|
|
||||||
shadow = make(map[string]bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
var m2 map[string]any
|
var m2 map[string]any
|
||||||
if prefix != "" {
|
if prefix != "" {
|
||||||
|
@ -1173,21 +1165,29 @@ func (v *Viper) postProcessingSliceFields(shadow map[string]bool, m map[string]a
|
||||||
if valValue.Kind() == reflect.Slice {
|
if valValue.Kind() == reflect.Slice {
|
||||||
for i := 0; i < valValue.Len(); i++ {
|
for i := 0; i < valValue.Len(); i++ {
|
||||||
item := valValue.Index(i)
|
item := valValue.Index(i)
|
||||||
if item.Kind() != reflect.Struct || !item.CanSet() {
|
iStr := strconv.FormatInt(int64(i), 10)
|
||||||
|
|
||||||
|
fmt.Printf("item %v\n", item)
|
||||||
|
if !item.CanSet() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
itemType := item.Type()
|
if item.Kind() == reflect.Struct {
|
||||||
for j := 0; j < item.NumField(); j++ {
|
itemType := item.Type()
|
||||||
field := itemType.Field(j)
|
for j := 0; j < item.NumField(); j++ {
|
||||||
// fmt.Printf("Field %d: Name=%s, Type=%v, Value=%v\n", j, field.Name, field.Type, item.Field(j).Interface())
|
field := itemType.Field(j)
|
||||||
|
sliceKey := prefix + k + v.keyDelim + iStr + v.keyDelim + field.Name
|
||||||
sliceKey := fmt.Sprintf("%s%s%s%d%s%s", prefix, k, v.keyDelim, i, v.keyDelim, field.Name)
|
// fmt.Printf("%s is slice\n", sliceKey)
|
||||||
shadow[strings.ToLower(sliceKey)] = true
|
|
||||||
// fmt.Printf("%s is slice\n", sliceKey)
|
|
||||||
|
|
||||||
|
if val, ok := v.getEnv(v.mergeWithEnvPrefix(sliceKey)); ok {
|
||||||
|
// fmt.Printf("Val is %v\n", val)
|
||||||
|
item.Field(j).SetString(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sliceKey := prefix + k + v.keyDelim + iStr
|
||||||
if val, ok := v.getEnv(v.mergeWithEnvPrefix(sliceKey)); ok {
|
if val, ok := v.getEnv(v.mergeWithEnvPrefix(sliceKey)); ok {
|
||||||
// fmt.Printf("Val is %v\n", val)
|
intValue, _ := strconv.ParseInt(val, 10, 32)
|
||||||
item.Field(j).SetString(val)
|
item.SetInt(intValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1202,9 +1202,8 @@ func (v *Viper) postProcessingSliceFields(shadow map[string]bool, m map[string]a
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// recursively merge to shadow map
|
// recursively merge to shadow map
|
||||||
shadow = v.postProcessingSliceFields(shadow, m2, fullKey)
|
v.postProcessingSliceFields(m2, fullKey)
|
||||||
}
|
}
|
||||||
return shadow
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) {
|
func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) {
|
||||||
|
|
|
@ -2611,6 +2611,10 @@ name: Steve
|
||||||
port: 8080
|
port: 8080
|
||||||
auth:
|
auth:
|
||||||
secret: 88888-88888
|
secret: 88888-88888
|
||||||
|
modes:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 3
|
||||||
clients:
|
clients:
|
||||||
- name: foo
|
- name: foo
|
||||||
- name: bar
|
- name: bar
|
||||||
|
@ -2641,6 +2645,7 @@ func TestSliceIndexAutomaticEnv(t *testing.T) {
|
||||||
Port int
|
Port int
|
||||||
Name string
|
Name string
|
||||||
Auth AuthConfig
|
Auth AuthConfig
|
||||||
|
Modes []int
|
||||||
Clients []ClientConfig
|
Clients []ClientConfig
|
||||||
Proxy ProxyConfig
|
Proxy ProxyConfig
|
||||||
}
|
}
|
||||||
|
@ -2655,10 +2660,12 @@ func TestSliceIndexAutomaticEnv(t *testing.T) {
|
||||||
assert.Equal(t, "foo", v.GetString("clients.0.name"))
|
assert.Equal(t, "foo", v.GetString("clients.0.name"))
|
||||||
assert.Equal(t, "bar", v.GetString("clients.1.name"))
|
assert.Equal(t, "bar", v.GetString("clients.1.name"))
|
||||||
assert.Equal(t, "proxy_foo", v.GetString("proxy.clients.0.name"))
|
assert.Equal(t, "proxy_foo", v.GetString("proxy.clients.0.name"))
|
||||||
|
assert.Equal(t, []int{1, 2, 3}, v.GetIntSlice("modes"))
|
||||||
|
|
||||||
// Override with env variable
|
// Override with env variable
|
||||||
t.Setenv("NAME", "Steven")
|
t.Setenv("NAME", "Steven")
|
||||||
t.Setenv("AUTH_SECRET", "99999-99999")
|
t.Setenv("AUTH_SECRET", "99999-99999")
|
||||||
|
t.Setenv("MODES_2", "300")
|
||||||
t.Setenv("CLIENTS_1_NAME", "baz")
|
t.Setenv("CLIENTS_1_NAME", "baz")
|
||||||
t.Setenv("PROXY_CLIENTS_0_NAME", "ProxyFoo")
|
t.Setenv("PROXY_CLIENTS_0_NAME", "ProxyFoo")
|
||||||
|
|
||||||
|
@ -2672,6 +2679,7 @@ func TestSliceIndexAutomaticEnv(t *testing.T) {
|
||||||
assert.Equal(t, "Steven", config.Name)
|
assert.Equal(t, "Steven", config.Name)
|
||||||
assert.Equal(t, 8080, config.Port)
|
assert.Equal(t, 8080, config.Port)
|
||||||
assert.Equal(t, "99999-99999", config.Auth.Secret)
|
assert.Equal(t, "99999-99999", config.Auth.Secret)
|
||||||
|
assert.Equal(t, []int{1, 2, 300}, config.Modes)
|
||||||
assert.Equal(t, "foo", config.Clients[0].Name)
|
assert.Equal(t, "foo", config.Clients[0].Name)
|
||||||
assert.Equal(t, "baz", config.Clients[1].Name)
|
assert.Equal(t, "baz", config.Clients[1].Name)
|
||||||
assert.Equal(t, "ProxyFoo", config.Proxy.Clients[0].Name)
|
assert.Equal(t, "ProxyFoo", config.Proxy.Clients[0].Name)
|
||||||
|
|
Loading…
Reference in a new issue