diff --git a/decoder.go b/decoder.go index 0cd1e79..6a4bb76 100644 --- a/decoder.go +++ b/decoder.go @@ -451,8 +451,15 @@ func (d *decoder) decodeStruct(name string, raw ast.Node, result reflect.Value) // Create the field name and decode fieldName = fmt.Sprintf("%s.%s", name, fieldName) for _, elem := range elems { + // If it is a sub-object, go through all the fields if obj, ok := elem.(ast.ObjectNode); ok { - elem = obj.Elem[0].Value + for _, elem := range obj.Elem { + if err := d.decode(fieldName, elem.Value, field); err != nil { + return err + } + } + + continue } if err := d.decode(fieldName, elem, field); err != nil { diff --git a/decoder_test.go b/decoder_test.go index f747ebb..1272511 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -197,13 +197,6 @@ func TestDecode_structureArray(t *testing.T) { Keys []KeyPolicy `hcl:"key"` } - var actual Policy - - err := Decode(&actual, testReadFile(t, "decode_policy.hcl")) - if err != nil { - t.Fatalf("err: %s", err) - } - expected := Policy{ Keys: []KeyPolicy{ KeyPolicy{ @@ -225,7 +218,21 @@ func TestDecode_structureArray(t *testing.T) { }, } - if !reflect.DeepEqual(actual, expected) { - t.Fatalf("Actual: %#v\n\nExpected: %#v", actual, expected) + files := []string{ + "decode_policy.hcl", + "decode_policy.json", + } + + for _, f := range files { + var actual Policy + + err := Decode(&actual, testReadFile(t, f)) + if err != nil { + t.Fatalf("err: %s", err) + } + + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("Input: %s\n\nActual: %#v\n\nExpected: %#v", f, actual, expected) + } } } diff --git a/json/parse.y b/json/parse.y index d647048..205f340 100644 --- a/json/parse.y +++ b/json/parse.y @@ -69,9 +69,15 @@ members: pair: STRING COLON value { + value := $3 + if obj, ok := value.(ast.ObjectNode); ok { + obj.K = $1 + value = obj + } + $$ = ast.AssignmentNode{ K: $1, - Value: $3, + Value: value, } } diff --git a/json/y.go b/json/y.go index 245bae2..9357ff3 100644 --- a/json/y.go +++ b/json/y.go @@ -65,7 +65,7 @@ const jsonEofCode = 1 const jsonErrCode = 2 const jsonMaxDepth = 200 -//line parse.y:178 +//line parse.y:184 //line yacctab:1 var jsonExca = []int{ @@ -395,13 +395,19 @@ jsondefault: case 6: //line parse.y:71 { + value := jsonS[jsonpt-0].item + if obj, ok := value.(ast.ObjectNode); ok { + obj.K = jsonS[jsonpt-2].str + value = obj + } + jsonVAL.assign = ast.AssignmentNode{ K: jsonS[jsonpt-2].str, - Value: jsonS[jsonpt-0].item, + Value: value, } } case 7: - //line parse.y:80 + //line parse.y:86 { jsonVAL.item = ast.LiteralNode{ Type: ast.ValueTypeString, @@ -409,22 +415,22 @@ jsondefault: } } case 8: - //line parse.y:87 + //line parse.y:93 { jsonVAL.item = jsonS[jsonpt-0].item } case 9: - //line parse.y:91 + //line parse.y:97 { jsonVAL.item = jsonS[jsonpt-0].obj } case 10: - //line parse.y:95 + //line parse.y:101 { jsonVAL.item = jsonS[jsonpt-0].array } case 11: - //line parse.y:99 + //line parse.y:105 { jsonVAL.item = ast.LiteralNode{ Type: ast.ValueTypeBool, @@ -432,7 +438,7 @@ jsondefault: } } case 12: - //line parse.y:106 + //line parse.y:112 { jsonVAL.item = ast.LiteralNode{ Type: ast.ValueTypeBool, @@ -440,7 +446,7 @@ jsondefault: } } case 13: - //line parse.y:113 + //line parse.y:119 { jsonVAL.item = ast.LiteralNode{ Type: ast.ValueTypeNil, @@ -448,27 +454,27 @@ jsondefault: } } case 14: - //line parse.y:122 + //line parse.y:128 { jsonVAL.array = ast.ListNode{} } case 15: - //line parse.y:126 + //line parse.y:132 { jsonVAL.array = ast.ListNode{Elem: jsonS[jsonpt-1].list} } case 16: - //line parse.y:132 + //line parse.y:138 { jsonVAL.list = []ast.Node{jsonS[jsonpt-0].item} } case 17: - //line parse.y:136 + //line parse.y:142 { jsonVAL.list = append(jsonS[jsonpt-2].list, jsonS[jsonpt-0].item) } case 18: - //line parse.y:142 + //line parse.y:148 { jsonVAL.item = ast.LiteralNode{ Type: ast.ValueTypeInt, @@ -476,7 +482,7 @@ jsondefault: } } case 19: - //line parse.y:149 + //line parse.y:155 { fs := fmt.Sprintf("%d.%s", jsonS[jsonpt-1].num, jsonS[jsonpt-0].str) f, err := strconv.ParseFloat(fs, 64) @@ -490,17 +496,17 @@ jsondefault: } } case 20: - //line parse.y:164 + //line parse.y:170 { jsonVAL.num = jsonS[jsonpt-0].num * -1 } case 21: - //line parse.y:168 + //line parse.y:174 { jsonVAL.num = jsonS[jsonpt-0].num } case 22: - //line parse.y:174 + //line parse.y:180 { jsonVAL.str = strconv.FormatInt(int64(jsonS[jsonpt-0].num), 10) } diff --git a/test-fixtures/decode_policy.json b/test-fixtures/decode_policy.json new file mode 100644 index 0000000..151864e --- /dev/null +++ b/test-fixtures/decode_policy.json @@ -0,0 +1,19 @@ +{ + "key": { + "": { + "policy": "read" + }, + + "foo/": { + "policy": "write" + }, + + "foo/bar/": { + "policy": "read" + }, + + "foo/bar/baz": { + "policy": "deny" + } + } +}