mirror of
https://github.com/spf13/viper
synced 2024-12-22 11:37:02 +00:00
feat(encoding)!: accept a map in the decoder interface
This interface is specific to decoding data into Viper's internal, so it's okay to make it Viper specific. BREAKING CHANGE: the decoder interface now accepts a map instead of an interface Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
This commit is contained in:
parent
6c1745665b
commit
e54e7a53a5
7 changed files with 30 additions and 31 deletions
|
@ -4,10 +4,10 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Decoder decodes the contents of b into a v representation.
|
// Decoder decodes the contents of b into v.
|
||||||
// It's primarily used for decoding contents of a file into a map[string]interface{}.
|
// It's primarily used for decoding contents of a file into a map[string]interface{}.
|
||||||
type Decoder interface {
|
type Decoder interface {
|
||||||
Decode(b []byte, v interface{}) error
|
Decode(b []byte, v map[string]interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -48,7 +48,7 @@ func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode calls the underlying Decoder based on the format.
|
// Decode calls the underlying Decoder based on the format.
|
||||||
func (e *DecoderRegistry) Decode(format string, b []byte, v interface{}) error {
|
func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]interface{}) error {
|
||||||
e.mu.RLock()
|
e.mu.RLock()
|
||||||
decoder, ok := e.decoders[format]
|
decoder, ok := e.decoders[format]
|
||||||
e.mu.RUnlock()
|
e.mu.RUnlock()
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
package encoding
|
package encoding
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type decoder struct {
|
type decoder struct {
|
||||||
v interface{}
|
v map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d decoder) Decode(_ []byte, v interface{}) error {
|
func (d decoder) Decode(_ []byte, v map[string]interface{}) error {
|
||||||
rv := v.(*string)
|
for key, value := range d.v {
|
||||||
*rv = d.v.(string)
|
v[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -44,7 +46,9 @@ func TestDecoderRegistry_Decode(t *testing.T) {
|
||||||
t.Run("OK", func(t *testing.T) {
|
t.Run("OK", func(t *testing.T) {
|
||||||
registry := NewDecoderRegistry()
|
registry := NewDecoderRegistry()
|
||||||
decoder := decoder{
|
decoder := decoder{
|
||||||
v: "decoded value",
|
v: map[string]interface{}{
|
||||||
|
"key": "value",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := registry.RegisterDecoder("myformat", decoder)
|
err := registry.RegisterDecoder("myformat", decoder)
|
||||||
|
@ -52,24 +56,24 @@ func TestDecoderRegistry_Decode(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var v string
|
v := map[string]interface{}{}
|
||||||
|
|
||||||
err = registry.Decode("myformat", []byte("some value"), &v)
|
err = registry.Decode("myformat", []byte("key: value"), v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v != "decoded value" {
|
if !reflect.DeepEqual(decoder.v, v) {
|
||||||
t.Fatalf("expected 'decoded value', got: %#v", v)
|
t.Fatalf("decoded value does not match the expected one\nactual: %+v\nexpected: %+v", v, decoder.v)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("DecoderNotFound", func(t *testing.T) {
|
t.Run("DecoderNotFound", func(t *testing.T) {
|
||||||
registry := NewDecoderRegistry()
|
registry := NewDecoderRegistry()
|
||||||
|
|
||||||
var v string
|
v := map[string]interface{}{}
|
||||||
|
|
||||||
err := registry.Decode("myformat", []byte("some value"), &v)
|
err := registry.Decode("myformat", nil, v)
|
||||||
if err != ErrDecoderNotFound {
|
if err != ErrDecoderNotFound {
|
||||||
t.Fatalf("expected ErrDecoderNotFound, got: %v", err)
|
t.Fatalf("expected ErrDecoderNotFound, got: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,6 @@ func (Codec) Encode(v interface{}) ([]byte, error) {
|
||||||
return buf.Bytes(), nil
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Codec) Decode(b []byte, v interface{}) error {
|
func (Codec) Decode(b []byte, v map[string]interface{}) error {
|
||||||
return hcl.Unmarshal(b, v)
|
return hcl.Unmarshal(b, &v)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,6 @@ func (Codec) Encode(v interface{}) ([]byte, error) {
|
||||||
return json.MarshalIndent(v, "", " ")
|
return json.MarshalIndent(v, "", " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Codec) Decode(b []byte, v interface{}) error {
|
func (Codec) Decode(b []byte, v map[string]interface{}) error {
|
||||||
return json.Unmarshal(b, v)
|
return json.Unmarshal(b, &v)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,21 +25,16 @@ func (Codec) Encode(v interface{}) ([]byte, error) {
|
||||||
return toml.Marshal(v)
|
return toml.Marshal(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Codec) Decode(b []byte, v interface{}) error {
|
func (Codec) Decode(b []byte, v map[string]interface{}) error {
|
||||||
tree, err := toml.LoadBytes(b)
|
tree, err := toml.LoadBytes(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if m, ok := v.(*map[string]interface{}); ok {
|
tmap := tree.ToMap()
|
||||||
vmap := *m
|
for key, value := range tmap {
|
||||||
tmap := tree.ToMap()
|
v[key] = value
|
||||||
for k, v := range tmap {
|
|
||||||
vmap[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tree.Unmarshal(v)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,6 @@ func (Codec) Encode(v interface{}) ([]byte, error) {
|
||||||
return yaml.Marshal(v)
|
return yaml.Marshal(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Codec) Decode(b []byte, v interface{}) error {
|
func (Codec) Decode(b []byte, v map[string]interface{}) error {
|
||||||
return yaml.Unmarshal(b, v)
|
return yaml.Unmarshal(b, &v)
|
||||||
}
|
}
|
||||||
|
|
2
viper.go
2
viper.go
|
@ -1635,7 +1635,7 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
|
||||||
|
|
||||||
switch format := strings.ToLower(v.getConfigType()); format {
|
switch format := strings.ToLower(v.getConfigType()); format {
|
||||||
case "yaml", "yml", "json", "toml", "hcl", "tfvars":
|
case "yaml", "yml", "json", "toml", "hcl", "tfvars":
|
||||||
err := decoderRegistry.Decode(format, buf.Bytes(), &c)
|
err := decoderRegistry.Decode(format, buf.Bytes(), c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ConfigParseError{err}
|
return ConfigParseError{err}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue