From 466bfe8664108313c52c9f9e50a671ad18f8b8e2 Mon Sep 17 00:00:00 2001 From: Cameron Moore Date: Fri, 9 Apr 2021 08:02:00 -0500 Subject: [PATCH] encoder: inline tables create map in nil interface (#496) Co-authored-by: Thomas Pelletier --- targets.go | 8 ++++++++ unmarshaler.go | 8 +++----- unmarshaler_test.go | 25 ++++++++++++++++++++++++- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/targets.go b/targets.go index a1e922f..0024264 100644 --- a/targets.go +++ b/targets.go @@ -159,6 +159,14 @@ func ensureValueIndexable(t target) error { var sliceInterfaceType = reflect.TypeOf([]interface{}{}) var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{}) +func ensureMapIfInterface(x target) { + v := x.get() + if v.Kind() == reflect.Interface && v.IsNil() { + newElement := reflect.MakeMap(mapStringInterfaceType) + x.set(newElement) + } +} + func setString(t target, v string) error { f := t.get() diff --git a/unmarshaler.go b/unmarshaler.go index b773831..885717b 100644 --- a/unmarshaler.go +++ b/unmarshaler.go @@ -120,11 +120,7 @@ func (d *decoder) fromParser(p *parser, v interface{}) error { // looks like a table. Otherwise the information // of a table is lost, and marshal cannot do the // round trip. - v := current.get() - if v.Kind() == reflect.Interface && v.IsNil() { - newElement := reflect.MakeMap(mapStringInterfaceType) - current.set(newElement) - } + ensureMapIfInterface(current) } case ast.ArrayTable: current, found, err = d.scopeWithArrayTable(root, node.Key()) @@ -381,6 +377,8 @@ func unmarshalFloat(x target, node ast.Node) error { func (d *decoder) unmarshalInlineTable(x target, node ast.Node) error { assertNode(ast.InlineTable, node) + ensureMapIfInterface(x) + it := node.Children() for it.Next() { n := it.Node() diff --git a/unmarshaler_test.go b/unmarshaler_test.go index ed472bb..89e57e2 100644 --- a/unmarshaler_test.go +++ b/unmarshaler_test.go @@ -296,6 +296,17 @@ B = "data"`, } }, }, + { + desc: "standard empty table", + input: `[A]`, + gen: func() test { + var v map[string]interface{} + return test{ + target: &v, + expected: &map[string]interface{}{`A`: map[string]interface{}{}}, + } + }, + }, { desc: "inline table", input: `Name = {First = "hello", Last = "world"}`, @@ -316,6 +327,17 @@ B = "data"`, } }, }, + { + desc: "inline empty table", + input: `A = {}`, + gen: func() test { + var v map[string]interface{} + return test{ + target: &v, + expected: &map[string]interface{}{`A`: map[string]interface{}{}}, + } + }, + }, { desc: "inline table inside array", input: `Names = [{First = "hello", Last = "world"}, {First = "ab", Last = "cd"}]`, @@ -713,6 +735,7 @@ type Integer484 struct { func (i Integer484) MarshalText() ([]byte, error) { return []byte(strconv.Itoa(i.Value)), nil } + func (i *Integer484) UnmarshalText(data []byte) error { conv, err := strconv.Atoi(string(data)) if err != nil { @@ -895,7 +918,7 @@ func TestIssue287(t *testing.T) { expected := map[string]interface{}{ "y": []interface{}{ []interface{}{ - nil, + map[string]interface{}{}, }, }, }