From ba1b12be14a2b53e25b6e9111cd1285ceb783eeb Mon Sep 17 00:00:00 2001 From: Thomas Pelletier Date: Wed, 6 Jan 2021 20:34:25 -0500 Subject: [PATCH] Fix ToMap for tables in nested mixed-type arrays (#461) Co-authored-by: Micah Stetson --- tomltree_write.go | 31 +++++++++++++++---------------- tomltree_write_test.go | 27 ++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/tomltree_write.go b/tomltree_write.go index d3c592d..0586122 100644 --- a/tomltree_write.go +++ b/tomltree_write.go @@ -510,27 +510,26 @@ func (t *Tree) ToMap() map[string]interface{} { case *Tree: result[k] = node.ToMap() case *tomlValue: - result[k] = node.toValue() + result[k] = tomlValueToGo(node.value) } } return result } -// toValue converts a tomlValue to a built-in Go type. -func (t *tomlValue) toValue() interface{} { - switch v := t.value.(type) { - case []interface{}: - s := make([]interface{}, len(v)) - for i := range s { - switch e := v[i].(type) { - case *Tree: - s[i] = e.ToMap() - default: - s[i] = e - } - } - return s - default: +func tomlValueToGo(v interface{}) interface{} { + if tree, ok := v.(*Tree); ok { + return tree.ToMap() + } + + rv := reflect.ValueOf(v) + + if rv.Kind() != reflect.Slice { return v } + values := make([]interface{}, rv.Len()) + for i := 0; i < rv.Len(); i++ { + item := rv.Index(i).Interface() + values[i] = tomlValueToGo(item) + } + return values } diff --git a/tomltree_write_test.go b/tomltree_write_test.go index c28e1e0..b254d76 100644 --- a/tomltree_write_test.go +++ b/tomltree_write_test.go @@ -296,12 +296,33 @@ func TestTreeWriteToMapWithArrayOfInlineTables(t *testing.T) { } func TestTreeWriteToMapWithTableInMixedArray(t *testing.T) { - tree, _ := Load(`a = ["foo", {bar = "baz"}]`) + tree, _ := Load(`a = [ + "foo", + [ + "bar", + {baz = "quux"}, + ], + [ + {a = "b"}, + {c = "d"}, + ], + ]`) expected := map[string]interface{}{ "a": []interface{}{ "foo", - map[string]interface{}{ - "bar": "baz", + []interface{}{ + "bar", + map[string]interface{}{ + "baz": "quux", + }, + }, + []interface{}{ + map[string]interface{}{ + "a": "b", + }, + map[string]interface{}{ + "c": "d", + }, }, }, }