mirror of
https://github.com/spf13/viper
synced 2025-05-11 06:37:27 +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...))
|
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
|
// Unmarshal unmarshals the config into a Struct. Make sure that the tags
|
||||||
// on the fields of the structure are properly set.
|
// on the fields of the structure are properly set.
|
||||||
func Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error {
|
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...))
|
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
|
// of time.Duration values & string slices
|
||||||
func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
|
func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
|
||||||
c := &mapstructure.DecoderConfig{
|
c := &mapstructure.DecoderConfig{
|
||||||
|
|
|
@ -518,6 +518,85 @@ func TestUnmarshaling(t *testing.T) {
|
||||||
assert.Equal(t, 35, Get("age"))
|
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) {
|
func TestUnmarshalExact(t *testing.T) {
|
||||||
vip := New()
|
vip := New()
|
||||||
target := &testUnmarshalExtra{}
|
target := &testUnmarshalExtra{}
|
||||||
|
|
Loading…
Add table
Reference in a new issue