mirror of https://github.com/spf13/viper.git
Implemented ability to unmarshal keys containing dots to structs.
Changed formatting of test objects for better git diffing and readibility. Fixed failing tests on Windows.
This commit is contained in:
parent
bd1db6bb8c
commit
99520c81d8
20
viper.go
20
viper.go
|
@ -1789,6 +1789,24 @@ outer:
|
|||
return shadow
|
||||
}
|
||||
|
||||
// Converts a fully qualified map key into a list of relative
|
||||
// map keys, allowing for keys to contain the delimiter themselves
|
||||
func keyComponents(v *Viper, key string) []string {
|
||||
var result []string
|
||||
components := strings.Split(key, v.keyDelim)
|
||||
for index := 0; index < len(components); index++ {
|
||||
potentialKey := strings.Join(components[0:index], v.keyDelim)
|
||||
if v.Get(potentialKey) != nil {
|
||||
result = append(result, potentialKey)
|
||||
}
|
||||
}
|
||||
result = append(result, key)
|
||||
for i := len(result) - 1; i > 0; i-- {
|
||||
result[i] = strings.Replace(result[i], result[i-1]+v.keyDelim, "", 1)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// AllSettings merges all settings and returns them as a map[string]interface{}.
|
||||
func AllSettings() map[string]interface{} { return v.AllSettings() }
|
||||
func (v *Viper) AllSettings() map[string]interface{} {
|
||||
|
@ -1801,7 +1819,7 @@ func (v *Viper) AllSettings() map[string]interface{} {
|
|||
// check just in case anything changes
|
||||
continue
|
||||
}
|
||||
path := strings.Split(k, v.keyDelim)
|
||||
path := keyComponents(v, k)
|
||||
lastKey := strings.ToLower(path[len(path)-1])
|
||||
deepestMap := deepSearch(m, path[0:len(path)-1])
|
||||
// set innermost value
|
||||
|
|
123
viper_test.go
123
viper_test.go
|
@ -13,6 +13,7 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
|
@ -45,6 +46,10 @@ clothing:
|
|||
age: 35
|
||||
eyes : brown
|
||||
beard: true
|
||||
emails:
|
||||
steve@hacker.com:
|
||||
created: 01/02/03
|
||||
active: true
|
||||
`)
|
||||
|
||||
var yamlExampleWithExtras = []byte(`Existing: true
|
||||
|
@ -207,11 +212,16 @@ func initHcl() {
|
|||
func initDirs(t *testing.T) (string, string, func()) {
|
||||
|
||||
var (
|
||||
testDirs = []string{`a a`, `b`, `c\c`, `D_`}
|
||||
testDirs = []string{`a a`, `b`, `C_`}
|
||||
config = `improbable`
|
||||
)
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
testDirs = append(testDirs, `d\d`)
|
||||
}
|
||||
|
||||
root, err := ioutil.TempDir("", "")
|
||||
require.NoError(t, err, "Failed to create temporary directory")
|
||||
|
||||
cleanup := true
|
||||
defer func() {
|
||||
|
@ -224,7 +234,7 @@ func initDirs(t *testing.T) (string, string, func()) {
|
|||
assert.Nil(t, err)
|
||||
|
||||
err = os.Chdir(root)
|
||||
assert.Nil(t, err)
|
||||
require.Nil(t, err)
|
||||
|
||||
for _, dir := range testDirs {
|
||||
err = os.Mkdir(dir, 0750)
|
||||
|
@ -415,7 +425,10 @@ func TestEmptyEnv(t *testing.T) {
|
|||
BindEnv("type") // Empty environment variable
|
||||
BindEnv("name") // Bound, but not set environment variable
|
||||
|
||||
os.Clearenv()
|
||||
os.Unsetenv("type")
|
||||
os.Unsetenv("TYPE")
|
||||
os.Unsetenv("name")
|
||||
os.Unsetenv("NAME")
|
||||
|
||||
os.Setenv("TYPE", "")
|
||||
|
||||
|
@ -431,7 +444,10 @@ func TestEmptyEnv_Allowed(t *testing.T) {
|
|||
BindEnv("type") // Empty environment variable
|
||||
BindEnv("name") // Bound, but not set environment variable
|
||||
|
||||
os.Clearenv()
|
||||
os.Unsetenv("type")
|
||||
os.Unsetenv("TYPE")
|
||||
os.Unsetenv("name")
|
||||
os.Unsetenv("NAME")
|
||||
|
||||
os.Setenv("TYPE", "")
|
||||
|
||||
|
@ -491,11 +507,98 @@ func TestSetEnvKeyReplacer(t *testing.T) {
|
|||
func TestAllKeys(t *testing.T) {
|
||||
initConfigs()
|
||||
|
||||
ks := sort.StringSlice{"title", "newkey", "owner.organization", "owner.dob", "owner.bio", "name", "beard", "ppu", "batters.batter", "hobbies", "clothing.jacket", "clothing.trousers", "clothing.pants.size", "age", "hacker", "id", "type", "eyes", "p_id", "p_ppu", "p_batters.batter.type", "p_type", "p_name", "foos",
|
||||
"title_dotenv", "type_dotenv", "name_dotenv",
|
||||
ks := sort.StringSlice{
|
||||
"title",
|
||||
"newkey",
|
||||
"owner.organization",
|
||||
"owner.dob",
|
||||
"owner.bio",
|
||||
"name",
|
||||
"beard",
|
||||
"ppu",
|
||||
"batters.batter",
|
||||
"hobbies",
|
||||
"clothing.jacket",
|
||||
"clothing.trousers",
|
||||
"clothing.pants.size",
|
||||
"age",
|
||||
"hacker",
|
||||
"id",
|
||||
"type",
|
||||
"eyes",
|
||||
"p_id",
|
||||
"p_ppu",
|
||||
"p_batters.batter.type",
|
||||
"p_type",
|
||||
"p_name",
|
||||
"foos",
|
||||
"title_dotenv",
|
||||
"type_dotenv",
|
||||
"name_dotenv",
|
||||
"emails.steve@hacker.com.active",
|
||||
"emails.steve@hacker.com.created",
|
||||
}
|
||||
dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
|
||||
all := map[string]interface{}{"owner": map[string]interface{}{"organization": "MongoDB", "bio": "MongoDB Chief Developer Advocate & Hacker at Large", "dob": dob}, "title": "TOML Example", "ppu": 0.55, "eyes": "brown", "clothing": map[string]interface{}{"trousers": "denim", "jacket": "leather", "pants": map[string]interface{}{"size": "large"}}, "id": "0001", "batters": map[string]interface{}{"batter": []interface{}{map[string]interface{}{"type": "Regular"}, map[string]interface{}{"type": "Chocolate"}, map[string]interface{}{"type": "Blueberry"}, map[string]interface{}{"type": "Devil's Food"}}}, "hacker": true, "beard": true, "hobbies": []interface{}{"skateboarding", "snowboarding", "go"}, "age": 35, "type": "donut", "newkey": "remote", "name": "Cake", "p_id": "0001", "p_ppu": "0.55", "p_name": "Cake", "p_batters": map[string]interface{}{"batter": map[string]interface{}{"type": "Regular"}}, "p_type": "donut", "foos": []map[string]interface{}{map[string]interface{}{"foo": []map[string]interface{}{map[string]interface{}{"key": 1}, map[string]interface{}{"key": 2}, map[string]interface{}{"key": 3}, map[string]interface{}{"key": 4}}}}, "title_dotenv": "DotEnv Example", "type_dotenv": "donut", "name_dotenv": "Cake"}
|
||||
all := map[string]interface{}{
|
||||
"owner": map[string]interface{}{
|
||||
"organization": "MongoDB",
|
||||
"bio": "MongoDB Chief Developer Advocate & Hacker at Large",
|
||||
"dob": dob,
|
||||
},
|
||||
"title": "TOML Example",
|
||||
"ppu": 0.55,
|
||||
"emails": map[string]interface{}{
|
||||
"steve@hacker.com": map[string]interface{}{
|
||||
"active": true,
|
||||
"created": "01/02/03",
|
||||
},
|
||||
},
|
||||
"eyes": "brown",
|
||||
"clothing": map[string]interface{}{
|
||||
"trousers": "denim",
|
||||
"jacket": "leather",
|
||||
"pants": map[string]interface{}{"size": "large"},
|
||||
},
|
||||
"id": "0001",
|
||||
"batters": map[string]interface{}{
|
||||
"batter": []interface{}{
|
||||
map[string]interface{}{"type": "Regular"},
|
||||
map[string]interface{}{"type": "Chocolate"},
|
||||
map[string]interface{}{"type": "Blueberry"},
|
||||
map[string]interface{}{"type": "Devil's Food"},
|
||||
},
|
||||
},
|
||||
"hacker": true,
|
||||
"beard": true,
|
||||
"hobbies": []interface{}{
|
||||
"skateboarding",
|
||||
"snowboarding",
|
||||
"go",
|
||||
},
|
||||
"age": 35,
|
||||
"type": "donut",
|
||||
"newkey": "remote",
|
||||
"name": "Cake",
|
||||
"p_id": "0001",
|
||||
"p_ppu": "0.55",
|
||||
"p_name": "Cake",
|
||||
"p_batters": map[string]interface{}{
|
||||
"batter": map[string]interface{}{"type": "Regular"},
|
||||
},
|
||||
"p_type": "donut",
|
||||
"foos": []map[string]interface{}{
|
||||
{
|
||||
"foo": []map[string]interface{}{
|
||||
{"key": 1},
|
||||
{"key": 2},
|
||||
{"key": 3},
|
||||
{"key": 4}},
|
||||
},
|
||||
},
|
||||
"title_dotenv": "DotEnv Example",
|
||||
"type_dotenv": "donut",
|
||||
"name_dotenv": "Cake",
|
||||
}
|
||||
|
||||
allkeys := sort.StringSlice(AllKeys())
|
||||
allkeys.Sort()
|
||||
|
@ -960,7 +1063,7 @@ func TestDirsSearch(t *testing.T) {
|
|||
err = v.ReadInConfig()
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, `value is `+path.Base(v.configPaths[0]), v.GetString(`key`))
|
||||
assert.Equal(t, `value is `+filepath.Base(v.configPaths[0]), v.GetString(`key`))
|
||||
}
|
||||
|
||||
func TestWrongDirsSearchNotFound(t *testing.T) {
|
||||
|
@ -1213,6 +1316,10 @@ clothing:
|
|||
pants:
|
||||
size: large
|
||||
trousers: denim
|
||||
emails:
|
||||
steve@hacker.com:
|
||||
active: true
|
||||
created: 01/02/03
|
||||
eyes: brown
|
||||
hacker: true
|
||||
hobbies:
|
||||
|
|
Loading…
Reference in New Issue