encoder: inline tables create map in nil interface (#496)
Co-authored-by: Thomas Pelletier <pelletier.thomas@gmail.com>
This commit is contained in:
@@ -159,6 +159,14 @@ func ensureValueIndexable(t target) error {
|
|||||||
var sliceInterfaceType = reflect.TypeOf([]interface{}{})
|
var sliceInterfaceType = reflect.TypeOf([]interface{}{})
|
||||||
var mapStringInterfaceType = reflect.TypeOf(map[string]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 {
|
func setString(t target, v string) error {
|
||||||
f := t.get()
|
f := t.get()
|
||||||
|
|
||||||
|
|||||||
+3
-5
@@ -120,11 +120,7 @@ func (d *decoder) fromParser(p *parser, v interface{}) error {
|
|||||||
// looks like a table. Otherwise the information
|
// looks like a table. Otherwise the information
|
||||||
// of a table is lost, and marshal cannot do the
|
// of a table is lost, and marshal cannot do the
|
||||||
// round trip.
|
// round trip.
|
||||||
v := current.get()
|
ensureMapIfInterface(current)
|
||||||
if v.Kind() == reflect.Interface && v.IsNil() {
|
|
||||||
newElement := reflect.MakeMap(mapStringInterfaceType)
|
|
||||||
current.set(newElement)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case ast.ArrayTable:
|
case ast.ArrayTable:
|
||||||
current, found, err = d.scopeWithArrayTable(root, node.Key())
|
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 {
|
func (d *decoder) unmarshalInlineTable(x target, node ast.Node) error {
|
||||||
assertNode(ast.InlineTable, node)
|
assertNode(ast.InlineTable, node)
|
||||||
|
|
||||||
|
ensureMapIfInterface(x)
|
||||||
|
|
||||||
it := node.Children()
|
it := node.Children()
|
||||||
for it.Next() {
|
for it.Next() {
|
||||||
n := it.Node()
|
n := it.Node()
|
||||||
|
|||||||
+24
-1
@@ -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",
|
desc: "inline table",
|
||||||
input: `Name = {First = "hello", Last = "world"}`,
|
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",
|
desc: "inline table inside array",
|
||||||
input: `Names = [{First = "hello", Last = "world"}, {First = "ab", Last = "cd"}]`,
|
input: `Names = [{First = "hello", Last = "world"}, {First = "ab", Last = "cd"}]`,
|
||||||
@@ -713,6 +735,7 @@ type Integer484 struct {
|
|||||||
func (i Integer484) MarshalText() ([]byte, error) {
|
func (i Integer484) MarshalText() ([]byte, error) {
|
||||||
return []byte(strconv.Itoa(i.Value)), nil
|
return []byte(strconv.Itoa(i.Value)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Integer484) UnmarshalText(data []byte) error {
|
func (i *Integer484) UnmarshalText(data []byte) error {
|
||||||
conv, err := strconv.Atoi(string(data))
|
conv, err := strconv.Atoi(string(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -895,7 +918,7 @@ func TestIssue287(t *testing.T) {
|
|||||||
expected := map[string]interface{}{
|
expected := map[string]interface{}{
|
||||||
"y": []interface{}{
|
"y": []interface{}{
|
||||||
[]interface{}{
|
[]interface{}{
|
||||||
nil,
|
map[string]interface{}{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user