Skip to content

Commit 149ccc0

Browse files
committed
Fix #776
Unmarshal from yamls with sequence merge key has been working fine for generic maps (aka. map[string]any types), but has been broken for structs. This commits fixes that, by properly handling marking a sequence as `isMerge` in keyToNodeMap. Perviously it always assumed that the entry node will be always a map, despite having logic for properly handling these.
1 parent 25e5d90 commit 149ccc0

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

decode.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,14 +1117,14 @@ func (d *Decoder) createDecodedNewValue(
11171117
return d.castToAssignableValue(newValue, typ, node)
11181118
}
11191119

1120-
func (d *Decoder) keyToNodeMap(ctx context.Context, node ast.Node, ignoreMergeKey bool, getKeyOrValueNode func(*ast.MapNodeIter) ast.Node) (map[string]ast.Node, error) {
1120+
func (d *Decoder) _keyToNodeMap(ctx context.Context, node ast.Node, ignoreMergeKey bool, isMerge bool, getKeyOrValueNode func(*ast.MapNodeIter) ast.Node) (map[string]ast.Node, error) {
11211121
d.stepIn()
11221122
defer d.stepOut()
11231123
if d.isExceededMaxDepth() {
11241124
return nil, ErrExceededMaxDepth
11251125
}
11261126

1127-
mapNode, err := d.getMapNode(node, false)
1127+
mapNode, err := d.getMapNode(node, isMerge)
11281128
if err != nil {
11291129
return nil, err
11301130
}
@@ -1137,7 +1137,7 @@ func (d *Decoder) keyToNodeMap(ctx context.Context, node ast.Node, ignoreMergeKe
11371137
if ignoreMergeKey {
11381138
continue
11391139
}
1140-
mergeMap, err := d.keyToNodeMap(ctx, mapIter.Value(), ignoreMergeKey, getKeyOrValueNode)
1140+
mergeMap, err := d._keyToNodeMap(ctx, mapIter.Value(), ignoreMergeKey, true, getKeyOrValueNode)
11411141
if err != nil {
11421142
return nil, err
11431143
}
@@ -1165,6 +1165,10 @@ func (d *Decoder) keyToNodeMap(ctx context.Context, node ast.Node, ignoreMergeKe
11651165
return keyToNodeMap, nil
11661166
}
11671167

1168+
func (d *Decoder) keyToNodeMap(ctx context.Context, node ast.Node, ignoreMergeKey bool, getKeyOrValueNode func(*ast.MapNodeIter) ast.Node) (map[string]ast.Node, error) {
1169+
return d._keyToNodeMap(ctx, node, ignoreMergeKey, false, getKeyOrValueNode)
1170+
}
1171+
11681172
func (d *Decoder) keyToKeyNodeMap(ctx context.Context, node ast.Node, ignoreMergeKey bool) (map[string]ast.Node, error) {
11691173
m, err := d.keyToNodeMap(ctx, node, ignoreMergeKey, func(nodeMap *ast.MapNodeIter) ast.Node { return nodeMap.Key() })
11701174
if err != nil {

decode_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,63 @@ merge:
657657
"merge": {{Key: "foo", Value: 1}, {Key: "bar", Value: 2}},
658658
},
659659
},
660+
// Issue #776
661+
{
662+
source: `
663+
a: &a
664+
value: 100
665+
666+
b: &b
667+
unit: "m/s"
668+
669+
c:
670+
<<: [*a, *b]
671+
d: var_x
672+
`,
673+
value: struct {
674+
C struct {
675+
Value int `yaml:"value"`
676+
Unit string `yaml:"unit"`
677+
D string `yaml:"d"`
678+
} `yaml:"c"`
679+
}{
680+
C: struct {
681+
Value int `yaml:"value"`
682+
Unit string `yaml:"unit"`
683+
D string `yaml:"d"`
684+
}{
685+
Value: 100,
686+
Unit: "m/s",
687+
D: "var_x",
688+
},
689+
},
690+
},
691+
{
692+
source: `
693+
a: &a
694+
value: 100
695+
696+
b: &b
697+
unit: "m/s"
698+
699+
c:
700+
<<: [*a, *b]
701+
d: var_x
702+
`,
703+
value: map[string]any{
704+
"c": map[string]any{
705+
"value": 100,
706+
"unit": "m/s",
707+
"d": "var_x",
708+
},
709+
"a": map[string]any{
710+
"value": 100,
711+
},
712+
"b": map[string]any{
713+
"unit": "m/s",
714+
},
715+
},
716+
},
660717

661718
// Flow sequence
662719
{

0 commit comments

Comments
 (0)