json/parser: empty list value should not flatten
Fixes https://github.com/hashicorp/terraform/issues/8886 While parsing JSON, an empty list value would be assumed to be a non-existent list of objects, and would be removed from the result. This may have never been the correct behavior but always worked okay because we previously didn't support lists as first class types. With the support of lists, we need to actually return the empty list as the type. If we return nothing, then projects like Terraform will think that the value was never set, which is false.
This commit is contained in:
parent
6f5bfed9a0
commit
c03d57b578
@ -274,6 +274,14 @@ func TestDecode_interface(t *testing.T) {
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"structure_list_empty.json",
|
||||
false,
|
||||
map[string]interface{}{
|
||||
"foo": []interface{}{},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"nested_block_comment.hcl",
|
||||
false,
|
||||
|
@ -48,6 +48,12 @@ func flattenListType(
|
||||
item *ast.ObjectItem,
|
||||
items []*ast.ObjectItem,
|
||||
frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
|
||||
// If the list is empty, keep the original list
|
||||
if len(ot.List) == 0 {
|
||||
items = append(items, item)
|
||||
return items, frontier
|
||||
}
|
||||
|
||||
// All the elements of this object must also be objects!
|
||||
for _, subitem := range ot.List {
|
||||
if _, ok := subitem.(*ast.ObjectType); !ok {
|
||||
|
@ -86,6 +86,7 @@ func (p *Parser) objectList() (*ast.ObjectList, error) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return node, nil
|
||||
}
|
||||
|
||||
|
@ -186,13 +186,13 @@ func TestFlattenObjects(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
`{
|
||||
"foo": [
|
||||
{
|
||||
"foo": "svh",
|
||||
"bar": "fatih"
|
||||
}
|
||||
]
|
||||
}`,
|
||||
"foo": [
|
||||
{
|
||||
"foo": "svh",
|
||||
"bar": "fatih"
|
||||
}
|
||||
]
|
||||
}`,
|
||||
[]ast.Node{
|
||||
&ast.ObjectType{},
|
||||
&ast.LiteralType{},
|
||||
@ -202,15 +202,33 @@ func TestFlattenObjects(t *testing.T) {
|
||||
},
|
||||
{
|
||||
`{
|
||||
"variable": {
|
||||
"foo": {}
|
||||
}
|
||||
}`,
|
||||
"variable": {
|
||||
"foo": {}
|
||||
}
|
||||
}`,
|
||||
[]ast.Node{
|
||||
&ast.ObjectType{},
|
||||
},
|
||||
1,
|
||||
},
|
||||
{
|
||||
`{
|
||||
"empty": []
|
||||
}`,
|
||||
[]ast.Node{
|
||||
&ast.ListType{},
|
||||
},
|
||||
1,
|
||||
},
|
||||
{
|
||||
`{
|
||||
"basic": [1, 2, 3]
|
||||
}`,
|
||||
[]ast.Node{
|
||||
&ast.ListType{},
|
||||
},
|
||||
1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, l := range literals {
|
||||
@ -360,7 +378,7 @@ func TestParse_inline(t *testing.T) {
|
||||
func equals(tb testing.TB, exp, act interface{}) {
|
||||
if !reflect.DeepEqual(exp, act) {
|
||||
_, file, line, _ := runtime.Caller(1)
|
||||
fmt.Printf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n", filepath.Base(file), line, exp, act)
|
||||
fmt.Printf("\033[31m%s:%d:\n\n\texp: %s\n\n\tgot: %s\033[39m\n\n", filepath.Base(file), line, exp, act)
|
||||
tb.FailNow()
|
||||
}
|
||||
}
|
||||
|
3
test-fixtures/structure_list_empty.json
Normal file
3
test-fixtures/structure_list_empty.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"foo": []
|
||||
}
|
Loading…
Reference in New Issue
Block a user