go-yaml icon indicating copy to clipboard operation
go-yaml copied to clipboard

yaml.Path to merge yaml docs

Open justinrush opened this issue 3 years ago • 0 comments

I'm using Path to merge two documents, which works well when the node in source exists in destination, but does not work when the node does not exist in the destination document. This sort of makes sense, because I'm doing a "replace" on something that doesn't actually exist in the destination, but I'm not sure how else to do this in a generic way.

The problem I'm trying to solve is that I have a main document that has two levels of nodes and I need to merge incoming documents into the main document at mainlevel1.someSubLevel; the parent.child node specified may or may not exist. If it doesn't exist, it should be added, if it does exist, it should be replaced.

This is the code I'm using to test:

func schrodinger(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func modifyYaml(dstDoc, srcDoc []byte, topLevel, middleLevel string) string {
	urlPath, err := yaml.PathString(fmt.Sprintf("$.%s.%s", topLevel, middleLevel))
	schrodinger(err)

	dstYaml, err := parser.ParseBytes(dstDoc, 0)
	schrodinger(err)

	dstYaml.Docs[0].ad

	err = urlPath.ReplaceWithReader(dstYaml, bytes.NewReader(srcDoc))
	schrodinger(err)

	return dstYaml.String()
}

func main() {
	// our main combined yaml document
	mainDocBytes := []byte(`---
level1:
  thing1:
    somevalue: []
  thing2:
    usefulthing: ""
level2:
  widget1:
    meh: {}
`)

	// a new yaml document describing changes for level1.thing1
	replaceExistingBytes := []byte(`---
somevalue: []
anotherValue: {}
`)

	// this output looks as expected
	fmt.Println("output with replacing existing node:")
	fmt.Println("-----------------------------------")
	fmt.Println(modifyYaml(mainDocBytes, replaceExistingBytes, "level1", "thing1"))
	fmt.Printf("\n\n\n")

	// a new yaml document describing a new node called level2.ugabuga
	addDocBytes := []byte(`---
usefulstuff: []
somestring: ""
`)

	// this output is the same as above - in other words, level2.ugabuga is not added to mainDoc
	fmt.Println("output with adding new node:")
	fmt.Println("-----------------------------------")
	fmt.Println(modifyYaml(mainDocBytes, addDocBytes, "level2", "ugabuga"))

}

output produced:

output with replacing existing node:
-----------------------------------
---
level1:
  thing1:
    somevalue: []
    anotherValue: {}
  thing2:
    usefulthing: ""
level2:
  widget1:
    meh: {}



output with adding new node:
-----------------------------------
---
level1:
  thing1:
    somevalue: []
  thing2:
    usefulthing: ""
level2:
  widget1:
    meh: {}

justinrush avatar Jun 01 '21 13:06 justinrush