mirror of
https://github.com/spf13/viper
synced 2025-05-07 20:57:18 +00:00
Merge 77aea9b385
into 3970ad177e
This commit is contained in:
commit
77ac5f7aa7
2 changed files with 122 additions and 1 deletions
44
viper.go
44
viper.go
|
@ -1097,6 +1097,27 @@ func (v *Viper) UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConf
|
|||
return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...))
|
||||
}
|
||||
|
||||
// UnmarshalKeyWithMeta performs UnmarshalKey and provides access to the
|
||||
// mapstructure.Metadata in an additional return value.
|
||||
func UnmarshalKeyWithMeta(key string, rawVal interface{}) (mapstructure.Metadata, error) {
|
||||
return v.UnmarshalKeyWithMeta(key, rawVal)
|
||||
}
|
||||
func (v *Viper) UnmarshalKeyWithMeta(key string, rawVal interface{}) (mapstructure.Metadata, error) {
|
||||
var meta mapstructure.Metadata
|
||||
config := defaultDecoderConfig(rawVal)
|
||||
config.Metadata = &meta
|
||||
|
||||
err := decode(v.Get(key), config)
|
||||
|
||||
if err != nil {
|
||||
return meta, err
|
||||
}
|
||||
|
||||
v.insensitiviseMaps()
|
||||
|
||||
return meta, nil
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals the config into a Struct. Make sure that the tags
|
||||
// on the fields of the structure are properly set.
|
||||
func Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error {
|
||||
|
@ -1107,7 +1128,28 @@ func (v *Viper) Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error
|
|||
return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
|
||||
}
|
||||
|
||||
// defaultDecoderConfig returns default mapsstructure.DecoderConfig with suppot
|
||||
// UnmarshalWithMeta performs Unmarshal and provides access to the
|
||||
// mapstructure.Metadata in an additional return value.
|
||||
func UnmarshalWithMeta(rawVal interface{}) (mapstructure.Metadata, error) {
|
||||
return v.UnmarshalWithMeta(rawVal)
|
||||
}
|
||||
func (v *Viper) UnmarshalWithMeta(rawVal interface{}) (mapstructure.Metadata, error) {
|
||||
var meta mapstructure.Metadata
|
||||
config := defaultDecoderConfig(rawVal)
|
||||
config.Metadata = &meta
|
||||
|
||||
err := decode(v.AllSettings(), config)
|
||||
|
||||
if err != nil {
|
||||
return meta, err
|
||||
}
|
||||
|
||||
v.insensitiviseMaps()
|
||||
|
||||
return meta, nil
|
||||
}
|
||||
|
||||
// defaultDecoderConfig returns default mapsstructure.DecoderConfig with support
|
||||
// of time.Duration values & string slices
|
||||
func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
|
||||
c := &mapstructure.DecoderConfig{
|
||||
|
|
|
@ -518,6 +518,85 @@ func TestUnmarshaling(t *testing.T) {
|
|||
assert.Equal(t, 35, Get("age"))
|
||||
}
|
||||
|
||||
func ExampleUnmarshalWithMeta() {
|
||||
v := New()
|
||||
type Lib struct {
|
||||
Name string
|
||||
Awesome bool
|
||||
Useful bool
|
||||
}
|
||||
var libsCfg struct {
|
||||
Libs map[string]Lib
|
||||
}
|
||||
v.config = map[string]interface{}{
|
||||
"libs": map[string]interface{}{
|
||||
"viper": map[string]interface{}{
|
||||
"name": "Viper",
|
||||
"awesome": true,
|
||||
"tagline": "Go configuration with fangs!",
|
||||
},
|
||||
},
|
||||
"numbers": []int{4, 8, 15, 16, 23, 42},
|
||||
}
|
||||
meta, _ := v.UnmarshalWithMeta(&libsCfg)
|
||||
// The keys slice is not stable. Sorting them in lexicographical
|
||||
// order allows comparison.
|
||||
sort.Strings(meta.Keys)
|
||||
sort.Strings(meta.Unused)
|
||||
fmt.Printf("%#v\n", meta.Keys)
|
||||
fmt.Printf("%#v", meta.Unused)
|
||||
// Output:
|
||||
// []string{"Libs", "Libs[viper]", "Libs[viper]", "Libs[viper].Awesome", "Libs[viper].Name"}
|
||||
// []string{"Libs[viper].tagline", "numbers"}
|
||||
}
|
||||
|
||||
func ExampleUnmarshalKeyWithMeta() {
|
||||
v := New()
|
||||
var lib struct {
|
||||
Name string
|
||||
Awesome bool
|
||||
Useful bool
|
||||
}
|
||||
v.config = map[string]interface{}{
|
||||
"libs": map[string]interface{}{
|
||||
"viper": map[string]interface{}{
|
||||
"name": "Viper",
|
||||
"awesome": true,
|
||||
"tagline": "Go configuration with fangs!",
|
||||
},
|
||||
},
|
||||
}
|
||||
meta, _ := v.UnmarshalKeyWithMeta("libs.viper", &lib)
|
||||
fmt.Println(meta.Keys)
|
||||
fmt.Println(meta.Unused)
|
||||
// Output:
|
||||
// [Name Awesome]
|
||||
// [tagline]
|
||||
}
|
||||
|
||||
func TestUnmarshalKeyWithMeta(t *testing.T) {
|
||||
v := New()
|
||||
v.SetConfigType("yaml")
|
||||
err := v.ReadConfig(bytes.NewBuffer(yamlExample))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var clothes struct {
|
||||
Jacket string
|
||||
Pants interface{}
|
||||
}
|
||||
meta, err := v.UnmarshalKeyWithMeta("clothing", &clothes)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
keys := []string{"Jacket", "Pants"}
|
||||
unused := []string{"trousers"}
|
||||
sort.Strings(meta.Keys)
|
||||
sort.Strings(meta.Unused)
|
||||
assert.Equal(t, keys, meta.Keys, "keys decoded")
|
||||
assert.Equal(t, unused, meta.Unused, "keys in config not in struct")
|
||||
}
|
||||
|
||||
func TestUnmarshalExact(t *testing.T) {
|
||||
vip := New()
|
||||
target := &testUnmarshalExtra{}
|
||||
|
|
Loading…
Add table
Reference in a new issue