Skip to content

Commit

Permalink
Marshal into empty interface{} (#433)
Browse files Browse the repository at this point in the history
Allows to marshal a TOML document into an empty `interface{}`, resulting
in a `map[string]interface{}`.

Fixes #432
  • Loading branch information
pelletier authored Sep 11, 2020
1 parent 196ce3a commit b76eb62
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
3 changes: 3 additions & 0 deletions marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
var localDateType = reflect.TypeOf(LocalDate{})
var localTimeType = reflect.TypeOf(LocalTime{})
var localDateTimeType = reflect.TypeOf(LocalDateTime{})
var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{})

// Check if the given marshal type maps to a Tree primitive
func isPrimitive(mtype reflect.Type) bool {
Expand Down Expand Up @@ -703,6 +704,8 @@ func (d *Decoder) unmarshal(v interface{}) error {

switch elem.Kind() {
case reflect.Struct, reflect.Map:
case reflect.Interface:
elem = mapStringInterfaceType
default:
return errors.New("only a pointer to struct or map can be unmarshaled from TOML")
}
Expand Down
53 changes: 53 additions & 0 deletions marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3888,3 +3888,56 @@ func TestPreserveNotEmptyField(t *testing.T) {
t.Errorf("Bad unmarshal: expected %+v, got %+v", expected, actual)
}
}

// github issue 432
func TestUnmarshalEmptyInterface(t *testing.T) {
doc := []byte(`User = "pelletier"`)

var v interface{}

err := Unmarshal(doc, &v)
if err != nil {
t.Fatal(err)
}

x, ok := v.(map[string]interface{})
if !ok {
t.Fatal(err)
}

if x["User"] != "pelletier" {
t.Fatalf("expected User=pelletier, but got %v", x)
}
}

func TestUnmarshalEmptyInterfaceDeep(t *testing.T) {
doc := []byte(`
User = "pelletier"
Age = 99
[foo]
bar = 42
`)

var v interface{}

err := Unmarshal(doc, &v)
if err != nil {
t.Fatal(err)
}

x, ok := v.(map[string]interface{})
if !ok {
t.Fatal(err)
}

expected := map[string]interface{}{
"User": "pelletier",
"Age": 99,
"foo": map[string]interface{}{
"bar": 42,
},
}

reflect.DeepEqual(x, expected)
}

0 comments on commit b76eb62

Please sign in to comment.