Skip to content
This repository was archived by the owner on Apr 1, 2025. It is now read-only.

Commit e93e6ae

Browse files
committed
Allow multiple merge keys
1 parent 3514762 commit e93e6ae

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

decode.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,11 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
770770
nerrs := len(d.terrors)
771771
for i := 0; i < l; i += 2 {
772772
ni := n.Content[i]
773+
if isMerge(ni) {
774+
// Merge keys ("<<") are discarded during processing, so don't need to be unique.
775+
continue
776+
}
777+
773778
for j := i + 2; j < l; j += 2 {
774779
nj := n.Content[j]
775780
if ni.Kind == nj.Kind && ni.Value == nj.Value {
@@ -816,7 +821,7 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
816821
mergedFields := d.mergedFields
817822
d.mergedFields = nil
818823

819-
var mergeNode *Node
824+
mergeNodes := []*Node{}
820825

821826
mapIsNew := false
822827
if out.IsNil() {
@@ -825,7 +830,7 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
825830
}
826831
for i := 0; i < l; i += 2 {
827832
if isMerge(n.Content[i]) {
828-
mergeNode = n.Content[i+1]
833+
mergeNodes = append(mergeNodes, n.Content[i+1])
829834
continue
830835
}
831836
k := reflect.New(kt).Elem()
@@ -852,8 +857,8 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
852857
}
853858

854859
d.mergedFields = mergedFields
855-
if mergeNode != nil {
856-
d.merge(n, mergeNode, out)
860+
for _, node := range mergeNodes {
861+
d.merge(n, node, out)
857862
}
858863

859864
d.stringMapType = stringMapType

decode_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,6 +1530,31 @@ func (s *S) TestMergeNestedStruct(c *C) {
15301530
c.Assert(testm["outer"], DeepEquals, wantm)
15311531
}
15321532

1533+
const doubleMerge = `
1534+
one: &one
1535+
a: 1
1536+
b: 2
1537+
1538+
two: &two
1539+
b: 3
1540+
c: 4
1541+
1542+
merged:
1543+
<<: *one
1544+
<<: *two
1545+
`
1546+
1547+
func (s *S) TestDoubleMerge(c *C) {
1548+
var m map[string]interface{}
1549+
err := yaml.Unmarshal([]byte(doubleMerge), &m)
1550+
c.Assert(err, IsNil)
1551+
c.Assert(m["merged"], DeepEquals, map[string]interface{}{
1552+
"a": 1,
1553+
"b": 3,
1554+
"c": 4,
1555+
})
1556+
}
1557+
15331558
var unmarshalNullTests = []struct {
15341559
input string
15351560
pristine, expected func() interface{}

0 commit comments

Comments
 (0)