I am trying to parse a Yaml file with go-yaml v3 and do some modifications on the YAML nodes but when I am writing back the content to a file, the yaml encoder adds an extra merge tag (!!merge
) wherever i have used <<
func main() {
sourceYaml := `
demo:
- name: some_name
location:
country:
meta_data: &meta_data
name: some_place
description: "name of a place"
<<: *meta_data`
node := yaml.Node{}
err := yaml.Unmarshal([]byte(sourceYaml), &node)
if err != nil {
log.Fatalf(err.Error())
os.Exit(1)
}
var b bytes.Buffer
yamlEncoder := yaml.NewEncoder(&b)
yamlEncoder.SetIndent(2)
err = yamlEncoder.Encode(&node)
if err != nil {
log.Fatalf(err.Error())
os.Exit(1)
}
fmt.Println(b.String())
err = os.WriteFile("test.yaml", b.Bytes(), 0o664)
if err != nil {
log.Fatalf(err.Error())
os.Exit(1)
}
}
This will print
demo:
- name: some_name
location:
country:
meta_data: &meta_data
name: some_place
description: "name of a place"
!!merge <<: *meta_data
I was expecting to get the same yaml printed but there was a difference in the output because of extra !!merge
string.
How can i remove this !!merge string from my generated file? I would consider a string replacement as the last solution but I want to avoid that first because my YAML can contain comments as well and I don't want to change that.
The tag is automatically filled by go-yaml:
When decoding, this field will always be set to the resolved tag, even when it wasn't explicitly provided in the YAML content.
Technically go-yaml is not wrong to output the tag, however their docs state
[the tag] will only be serialized into the representation if TaggedStyle is used or the implicit tag diverges from the provided one.
„The implicit tag“ is !!merge
(as your code shows) so go-yaml shouldn't output it. You could file a bug report for this.
In the meantime, you can remove the tag after unmarshaling with a function like this:
func removeMerge(node *yaml.Node) {
if node.Tag == "!!merge" {
node.Tag = ""
}
for _, child := range node.Content {
removeMerge(child)
}
}