Fixed processing of nested data

This commit is contained in:
Mike Farah
2025-12-08 20:30:47 +11:00
parent df3101ce53
commit 6270c29f54
2 changed files with 27 additions and 16 deletions
+14 -15
View File
@@ -81,14 +81,7 @@ func (dec *hclDecoder) Decode() (*CandidateNode, error) {
// process blocks // process blocks
for _, block := range body.Blocks { for _, block := range body.Blocks {
// build a key from type and labels to preserve identity addBlockToMapping(root, block, dec.fileBytes)
keyName := block.Type
if len(block.Labels) > 0 {
keyName = keyName + " " + strings.Join(block.Labels, " ")
}
keyNode := createStringScalarNode(keyName)
valueNode := hclBodyToNode(block.Body, dec.fileBytes)
root.AddKeyValueChild(keyNode, valueNode)
} }
dec.documentIndex++ dec.documentIndex++
@@ -104,17 +97,23 @@ func hclBodyToNode(body *hclsyntax.Body, src []byte) *CandidateNode {
node.AddKeyValueChild(key, val) node.AddKeyValueChild(key, val)
} }
for _, block := range body.Blocks { for _, block := range body.Blocks {
keyName := block.Type addBlockToMapping(node, block, src)
if len(block.Labels) > 0 {
keyName = keyName + " " + strings.Join(block.Labels, " ")
}
key := createStringScalarNode(keyName)
val := hclBodyToNode(block.Body, src)
node.AddKeyValueChild(key, val)
} }
return node return node
} }
// addBlockToMapping nests block type and labels into the parent mapping, merging children.
func addBlockToMapping(parent *CandidateNode, block *hclsyntax.Block, src []byte) {
bodyNode := hclBodyToNode(block.Body, src)
chain := bodyNode
for i := len(block.Labels) - 1; i >= 0; i-- {
wrap := &CandidateNode{Kind: MappingNode}
wrap.AddKeyValueChild(createStringScalarNode(block.Labels[i]), chain)
chain = wrap
}
parent.AddKeyValueChild(createStringScalarNode(block.Type), chain)
}
func convertHclExprToNode(expr hclsyntax.Expression, src []byte) *CandidateNode { func convertHclExprToNode(expr hclsyntax.Expression, src []byte) *CandidateNode {
// handle literal values directly // handle literal values directly
switch e := expr.(type) { switch e := expr.(type) {
+13 -1
View File
@@ -6,6 +6,12 @@ import (
"github.com/mikefarah/yq/v4/test" "github.com/mikefarah/yq/v4/test"
) )
var nestedExample = `service "http" "web_proxy" {
listen_addr = "127.0.0.1:8080"
}`
var nestedExampleYaml = "service:\n http:\n web_proxy:\n listen_addr: \"127.0.0.1:8080\"\n"
var hclFormatScenarios = []formatScenario{ var hclFormatScenarios = []formatScenario{
{ {
description: "Simple decode", description: "Simple decode",
@@ -25,6 +31,12 @@ var hclFormatScenarios = []formatScenario{
expected: "io_mode = async\n", expected: "io_mode = async\n",
scenarioType: "roundtrip", scenarioType: "roundtrip",
}, },
{
description: "Nested decode",
input: nestedExample,
expected: nestedExampleYaml,
scenarioType: "decode",
},
{ {
description: "Template decode", description: "Template decode",
input: `message = "Hello, ${name}!"`, input: `message = "Hello, ${name}!"`,
@@ -124,7 +136,7 @@ var hclFormatScenarios = []formatScenario{
{ {
description: "block with labels", description: "block with labels",
input: `resource "aws_instance" "example" { ami = "ami-12345" }`, input: `resource "aws_instance" "example" { ami = "ami-12345" }`,
expected: "resource aws_instance example:\n ami: \"ami-12345\"\n", expected: "resource:\n aws_instance:\n example:\n ami: \"ami-12345\"\n",
scenarioType: "decode", scenarioType: "decode",
}, },
{ {