decode more complex structs
This commit is contained in:
parent
8e81ec8b57
commit
c3506acf01
49
decoder.go
49
decoder.go
@ -25,7 +25,18 @@ func DecodeAST(out interface{}, obj *ast.ObjectNode) error {
|
||||
}
|
||||
|
||||
func decode(name string, n ast.Node, result reflect.Value) error {
|
||||
switch result.Kind() {
|
||||
k := result
|
||||
|
||||
// If we have an interface with a valid value, we use that
|
||||
// for the check.
|
||||
if result.Kind() == reflect.Interface {
|
||||
elem := result.Elem()
|
||||
if elem.IsValid() {
|
||||
k = elem
|
||||
}
|
||||
}
|
||||
|
||||
switch k.Kind() {
|
||||
case reflect.Int:
|
||||
return decodeInt(name, n, result)
|
||||
case reflect.Interface:
|
||||
@ -185,15 +196,41 @@ func decodeMap(name string, raw ast.Node, result reflect.Value) error {
|
||||
}
|
||||
|
||||
func decodeSlice(name string, raw ast.Node, result reflect.Value) error {
|
||||
// Create the slice
|
||||
n, ok := raw.(ast.ListNode)
|
||||
if !ok {
|
||||
return fmt.Errorf("%s: not a list type", name)
|
||||
}
|
||||
|
||||
// If we have an interface, then we can address the interface,
|
||||
// but not the slice itself, so get the element but set the interface
|
||||
set := result
|
||||
if result.Kind() == reflect.Interface {
|
||||
result = result.Elem()
|
||||
}
|
||||
|
||||
// Create the slice if it isn't nil
|
||||
resultType := result.Type()
|
||||
resultElemType := resultType.Elem()
|
||||
resultSliceType := reflect.SliceOf(resultElemType)
|
||||
resultSlice := reflect.MakeSlice(
|
||||
resultSliceType, 0, 0)
|
||||
if result.IsNil() {
|
||||
resultSliceType := reflect.SliceOf(resultElemType)
|
||||
result = reflect.MakeSlice(
|
||||
resultSliceType, 0, 0)
|
||||
}
|
||||
|
||||
result.Set(resultSlice)
|
||||
for i, elem := range n.Elem {
|
||||
fieldName := fmt.Sprintf("%s[%d]", name, i)
|
||||
|
||||
// Decode
|
||||
val := reflect.Indirect(reflect.New(resultElemType))
|
||||
if err := decode(fieldName, elem, val); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Append it onto the slice
|
||||
result = reflect.Append(result, val)
|
||||
}
|
||||
|
||||
set.Set(result)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ func TestDecode(t *testing.T) {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
var out map[string]interface{}
|
||||
var out interface{}
|
||||
err = Decode(&out, string(d))
|
||||
if (err != nil) != tc.Err {
|
||||
t.Fatalf("Input: %s\n\nError: %s", tc.File, err)
|
||||
@ -72,6 +72,10 @@ func TestDecode_equal(t *testing.T) {
|
||||
"structure.hcl",
|
||||
"structure_flat.json",
|
||||
},
|
||||
{
|
||||
"structure_multi.hcl",
|
||||
"structure_multi.json",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
7
test-fixtures/structure_multi.hcl
Normal file
7
test-fixtures/structure_multi.hcl
Normal file
@ -0,0 +1,7 @@
|
||||
foo "baz" {
|
||||
key = 7
|
||||
}
|
||||
|
||||
foo "bar" {
|
||||
key = 12
|
||||
}
|
11
test-fixtures/structure_multi.json
Normal file
11
test-fixtures/structure_multi.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"foo": [{
|
||||
"baz": [{
|
||||
"key": 7
|
||||
}]
|
||||
}, {
|
||||
"bar": [{
|
||||
"key": 12
|
||||
}]
|
||||
}]
|
||||
}
|
Loading…
Reference in New Issue
Block a user