Home > Software engineering >  Is there a way to add a yaml node to an existing yaml document in golang?
Is there a way to add a yaml node to an existing yaml document in golang?

Time:10-05

I am reading a yaml file with goyaml lib. I intend to modify some of its entries and add an entry if the key to be added is not already present.

e.g.

original yaml

root:
  entry1: val1

1 mod and 1 add target yaml

root:
 entry1: valUpdated
 entry2: newkey added

I cannot find any yaml lib which can allow me to add a node to yaml.

thanks for your help

CodePudding user response:

You can do this with go-yaml if you unmarshal to yaml.Node:

package main

import (
    "os"

    "gopkg.in/yaml.v3"
)

var input = []byte(`root:
  entry1: val1`)

func main() {
    var document yaml.Node
    if err := yaml.Unmarshal(input, &document); err != nil {
        panic(err)
    }
    data := document.Content[0]
    var rootVal *yaml.Node
    for i := 0; i < len(data.Content); i  = 2 {
        node := data.Content[i]
        if node.Kind == yaml.ScalarNode && node.Value == "root" {
            rootVal = data.Content[i 1]
            break
        }
    }
    if rootVal == nil {
        panic("root key missing")
    }

    found := false
    for i := 0; i < len(rootVal.Content); i  = 2 {
        node := rootVal.Content[i]
        if node.Kind != yaml.ScalarNode {
            continue
        }
        switch node.Value {
        case "entry1":
            rootVal.Content[i 1].SetString("valUpdated")
        case "entry2":
            found = true
        }
    }
    if !found {
        var key, value yaml.Node
        key.SetString("entry2")
        value.SetString("newkey added")
        rootVal.Content = append(rootVal.Content, &key, &value)
    }
    out, err := yaml.Marshal(data)
    if err != nil {
        panic(err)
    }
    os.Stdout.Write(out)
}

output:

root:
    entry1: valUpdated
    entry2: newkey added

Playground link

Unmarshal gets you a document node with the root node as sole content node. Marshal expects the root node as data, so you feed data instead of document into it. I am not really sure why the API is like that.

  • Related