diff --git a/README.md b/README.md index b081df9..8c592b1 100644 --- a/README.md +++ b/README.md @@ -441,6 +441,52 @@ will be returned instead. E.g. GetString("datastore.metric.host") //returns "0.0.0.0" ``` +### Extract sub-tree + +Extract sub-tree from Viper. + +For example, `viper` represents: + +```json +app: + cache1: + max-items: 100 + item-size: 64 + cache2: + max-items: 200 + item-size: 80 +``` + +After executing: + +```go +subv := viper.Sub("app.cache1") +``` + +`subv` represents: + +```json +max-items: 100 +item-size: 64 +``` + +Suppose we have: + +```go +func NewCache(cfg *Viper) *Cache {...} +``` + +which creates a cache based on config information formatted as `subv`. +Now it's easy to create these 2 caches separately as: + +```go +cfg1 := viper.Sub("app.cache1") +cache1 := NewCache(cfg1) + +cfg2 := viper.Sub("app.cache2") +cache2 := NewCache(cfg2) +``` + ### Unmarshaling You also have the option of Unmarshaling all or a specific value to a struct, map, diff --git a/viper.go b/viper.go index 6f204b1..a671c1f 100644 --- a/viper.go +++ b/viper.go @@ -513,6 +513,18 @@ func (v *Viper) Get(key string) interface{} { return val } +// Returns new Viper instance representing a sub tree of this instance +func Sub(key string) *Viper { return v.Sub(key) } +func (v *Viper) Sub(key string) *Viper { + data, ok := v.Get(key).(map[string]interface{}) + if !ok { + return nil + } + subv := New() + subv.config = data + return subv +} + // Returns the value associated with the key as a string func GetString(key string) string { return v.GetString(key) } func (v *Viper) GetString(key string) string { diff --git a/viper_test.go b/viper_test.go index bfbfcec..0c71549 100644 --- a/viper_test.go +++ b/viper_test.go @@ -724,3 +724,16 @@ func TestWrongDirsSearchNotFound(t *testing.T) { // been ignored by the client, the default still loads assert.Equal(t, `default`, v.GetString(`key`)) } + +func TestSub(t *testing.T) { + v := New() + v.SetConfigType("yaml") + v.ReadConfig(bytes.NewBuffer(yamlExample)) + + subv := v.Sub("clothing.pants") + assert.Equal(t, v.Get("clothing.pants.size"), subv.Get("size")) + + subv = v.Sub("clothing.pants.size") + assert.Equal(t, subv, (*Viper)(nil)) +} +