From 65159dc252c909af87489733f6806dcccf41ee50 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 21 Aug 2014 13:32:31 -0700 Subject: [PATCH] Don't double-nest lists of objects --- decoder.go | 14 ++++++++++++-- decoder_test.go | 29 +++++++++++++++++++++++++++++ test-fixtures/structure_list.hcl | 6 ++++++ test-fixtures/structure_list.json | 7 +++++++ 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 test-fixtures/structure_list.hcl create mode 100644 test-fixtures/structure_list.json diff --git a/decoder.go b/decoder.go index dec5d5f..81c939d 100644 --- a/decoder.go +++ b/decoder.go @@ -31,7 +31,9 @@ func DecodeObject(out interface{}, n *hcl.Object) error { return d.decode("root", n, reflect.ValueOf(out).Elem()) } -type decoder struct{} +type decoder struct{ + last, current reflect.Kind +} func (d *decoder) decode(name string, o *hcl.Object, result reflect.Value) error { k := result @@ -45,6 +47,11 @@ func (d *decoder) decode(name string, o *hcl.Object, result reflect.Value) error } } + // Keep track of the last known type and the current since we use + // some context to determine things. + d.last = d.current + d.current = k.Kind() + switch k.Kind() { case reflect.Bool: return d.decodeBool(name, o, result) @@ -112,7 +119,10 @@ func (d *decoder) decodeInterface(name string, o *hcl.Object, result reflect.Val switch o.Type { case hcl.ValueTypeObject: - if name == "root" { + // If we're at the root or we're directly within a slice, then we + // decode objects into map[string]interface{}, otherwise we decode + // them into lists. + if d.last == reflect.Invalid || d.last == reflect.Slice { var temp map[string]interface{} tempVal := reflect.ValueOf(temp) result := reflect.MakeMap( diff --git a/decoder_test.go b/decoder_test.go index ab5ce9b..ffbceca 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -97,9 +97,38 @@ func TestDecode_interface(t *testing.T) { }, }, }, + { + "structure_list.hcl", + false, + map[string]interface{}{ + "foo": []map[string]interface{}{ + map[string]interface{}{ + "key": 7, + }, + map[string]interface{}{ + "key": 12, + }, + }, + }, + }, + { + "structure_list.json", + false, + map[string]interface{}{ + "foo": []map[string]interface{}{ + map[string]interface{}{ + "key": 7, + }, + map[string]interface{}{ + "key": 12, + }, + }, + }, + }, } for _, tc := range cases { + if tc.File != "empty.hcl" { continue } d, err := ioutil.ReadFile(filepath.Join(fixtureDir, tc.File)) if err != nil { t.Fatalf("err: %s", err) diff --git a/test-fixtures/structure_list.hcl b/test-fixtures/structure_list.hcl new file mode 100644 index 0000000..33193ae --- /dev/null +++ b/test-fixtures/structure_list.hcl @@ -0,0 +1,6 @@ +foo { + key = 7 +} +foo { + key = 12 +} diff --git a/test-fixtures/structure_list.json b/test-fixtures/structure_list.json new file mode 100644 index 0000000..806a60e --- /dev/null +++ b/test-fixtures/structure_list.json @@ -0,0 +1,7 @@ +{ + "foo": [{ + "key": 7 + }, { + "key": 12 + }] +}