修改现有的Yaml文件并添加新数据和注释

修改现有的Yaml文件并添加新数据和注释,第1张

修改现有的Yaml文件并添加新数据和注释

首先,让我开始说使用yaml.Node从有效yaml编组时不会产生有效的yaml,如以下示例所示。可能应该提出问题。

package mainimport (    "fmt"    "log"    "gopkg.in/yaml.v3")var (    sourceYaml = `version: 1type: verbosekind : bfr# my list of applicationsapplications:#  First app  - name: app1    kind: nodejs    path: app1    exec:      platforms: k8s      builder: test`)func main() {    t := yaml.Node{}    err := yaml.Unmarshal([]byte(sourceYaml), &t)    if err != nil {        log.Fatalf("error: %v", err)    }    b, err := yaml.Marshal(&t)    if err != nil {        log.Fatal(err)    }    fmt.Println(string(b))}

在go版本go1.12.3 windows / amd64中产生以下无效的Yaml

version: 1type: verbosekind: bfr# my list of applicationsapplications:-   #  First appname: app1    kind: nodejs    path: app1    exec:        platforms: k8s        builder: test

其次,使用诸如

type VTS struct {    Version string       `yaml:"version" json:"version"`    Types   string       `yaml:"type" json:"type"`    Kind    string       `yaml:"kind,omitempty" json:"kind,omitempty"`    Apps    yaml.Node `yaml:"applications,omitempty" json:"applications,omitempty"`}

从ubuntu的博客和源文档中可以看出,它可以正确识别结构中的节点(分别是节点)并分别构建该树,但事实并非如此。取消编组时,它将提供正确的节点树,但是当重新编组时,它将产生以下yaml,其中包含yaml.Node公开的所有字段。可悲的是我们不能走这条路,必须找到另一条路。

version: "1"type: verbosekind: bfrapplications:    kind: 2    style: 0    tag: '!!seq'    value: ""    anchor: ""    alias: null    content:    -   #  First appname: app1        kind: nodejs        path: app1        exec: platforms: k8s builder: test    headcomment: ""    linecomment: ""    footcomment: ""    line: 9    column: 3

现在,我们可以忽略结构中yaml.Nodes的第一个问题和程序错误(位于gopkg.in/yaml.v3
v3.0.0-20190409140830-cdc409dda467上),我们可以开始 *** 作程序包公开的Nodes。不幸的是,没有可以轻松添加节点的抽象,因此用途可能会有所不同,并且标识节点可能会很麻烦。反思可能会对您有所帮助,因此我将其作为练习留给您。

您会发现注释spew.Dump以一种不错的格式转储了整个节点Tree,这有助于在将Node添加到源树时进行调试。

当然,您也可以删除节点,只需要确定需要删除的特定节点即可。您只需确保删除父节点(如果它们是图或序列)即可。

package mainimport (    "encoding/json"    "fmt"    "log"    "gopkg.in/yaml.v3")var (    sourceYaml = `version: 1type: verbosekind : bfr# my list of applicationsapplications:#  First app  - name: app1    kind: nodejs    path: app1    exec:      platforms: k8s      builder: test`    modifyJsonSource = `[    {        "comment": "Second app",        "name": "app2",        "kind": "golang",        "path": "app2",        "exec": { "platforms": "dockerh", "builder": "test"        }    }]`)// VTS Need to Make Fields Public otherwise unmarshalling will not fill in the unexported fields.type VTS struct {    Version string       `yaml:"version" json:"version"`    Types   string       `yaml:"type" json:"type"`    Kind    string       `yaml:"kind,omitempty" json:"kind,omitempty"`    Apps    Applications `yaml:"applications,omitempty" json:"applications,omitempty"`}type Applications []struct {    Name string `yaml:"name,omitempty" json:"name,omitempty"`    Kind string `yaml:"kind,omitempty" json:"kind,omitempty"`    Path string `yaml:"path,omitempty" json:"path,omitempty"`    Exec struct {        Platforms string `yaml:"platforms,omitempty" json:"platforms,omitempty"`        Builder   string `yaml:"builder,omitempty" json:"builder,omitempty"`    } `yaml:"exec,omitempty" json:"exec,omitempty"`    Comment string `yaml:"comment,omitempty" json:"comment,omitempty"`}func main() {    t := yaml.Node{}    err := yaml.Unmarshal([]byte(sourceYaml), &t)    if err != nil {        log.Fatalf("error: %v", err)    }    // Look for the Map Node with the seq array of items    applicationNode := iterateNode(&t, "applications")    // spew.Dump(iterateNode(&t, "applications"))    var addFromJson Applications    err = json.Unmarshal([]byte(modifyJsonSource), &addFromJson)    if err != nil {        log.Fatalf("error: %v", err)    }    // Delete the Original Applications the following options:    // applicationNode.Content = []*yaml.Node{}    // deleteAllContents(applicationNode)    deleteApplication(applicationNode, "name", "app1")    for _, app := range addFromJson {        // Build New Map Node for new sequences coming in from json        mapNode := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}        // Build Name, Kind, and Path Nodes        mapNode.Content = append(mapNode.Content, buildStringNodes("name", app.Name, app.Comment)...)        mapNode.Content = append(mapNode.Content, buildStringNodes("kind", app.Kind, "")...)        mapNode.Content = append(mapNode.Content, buildStringNodes("path", app.Path, "")...)        // Build the Exec Nodes and the Platform and Builder Nodes within it        keyMapNode, keyMapValuesNode := buildMapNodes("exec")        keyMapValuesNode.Content = append(keyMapValuesNode.Content, buildStringNodes("platform", app.Exec.Platforms, "")...)        keyMapValuesNode.Content = append(keyMapValuesNode.Content, buildStringNodes("builder", app.Exec.Builder, "")...)        // Add to parent map Node        mapNode.Content = append(mapNode.Content, keyMapNode, keyMapValuesNode)        // Add to applications Node        applicationNode.Content = append(applicationNode.Content, mapNode)    }    // spew.Dump(t)    b, err := yaml.Marshal(&t)    if err != nil {        log.Fatal(err)    }    fmt.Println(string(b))}// iterateNode will recursive look for the node following the identifier Node,// as go-yaml has a node for the key and the value itself// we want to manipulate the value Nodefunc iterateNode(node *yaml.Node, identifier string) *yaml.Node {    returnNode := false    for _, n := range node.Content {        if n.Value == identifier { returnNode = true continue        }        if returnNode { return n        }        if len(n.Content) > 0 { ac_node := iterateNode(n, identifier) if ac_node != nil {     return ac_node }        }    }    return nil}// deleteAllContents will remove all the contents of a node// Mark sure to pass the correct node in otherwise bad things will happenfunc deleteAllContents(node *yaml.Node) {    node.Content = []*yaml.Node{}}// deleteApplication expects that a sequence Node with all the applications are present// if the key value are not found it will not log any errors, and return silently// this is expecting a map like structure for the applicationsfunc deleteApplication(node *yaml.Node, key, value string) {    state := -1    indexRemove := -1    for index, parentNode := range node.Content {        for _, childNode := range parentNode.Content { if key == childNode.Value && state == -1 {     state += 1     continue // found expected move onto next } if value == childNode.Value && state == 0 {     state += 1     indexRemove = index     break // found the target exit out of the loop } else if state == 0 {     state = -1 }        }    }    if state == 1 {        // Remove node from contents        // node.Content = append(node.Content[:indexRemove], node.Content[indexRemove+1:]...)        // Don't Do this you might have a potential memory leak source: https://github.com/golang/go/wiki/SliceTricks        // Since the underlying nodes are pointers        length := len(node.Content)        copy(node.Content[indexRemove:], node.Content[indexRemove+1:])        node.Content[length-1] = nil        node.Content = node.Content[:length-1]    }}// buildStringNodes builds Nodes for a single key: value instancefunc buildStringNodes(key, value, comment string) []*yaml.Node {    keyNode := &yaml.Node{        Kind:        yaml.ScalarNode,        Tag:         "!!str",        Value:       key,        HeadComment: comment,    }    valueNode := &yaml.Node{        Kind:  yaml.ScalarNode,        Tag:   "!!str",        Value: value,    }    return []*yaml.Node{keyNode, valueNode}}// buildMapNodes builds Nodes for a key: map instancefunc buildMapNodes(key string) (*yaml.Node, *yaml.Node) {    n1, n2 := &yaml.Node{        Kind:  yaml.ScalarNode,        Tag:   "!!str",        Value: key,    }, &yaml.Node{Kind: yaml.MappingNode,        Tag: "!!map",    }    return n1, n2}

生产yaml

version: 1type: verbosekind: bfr# my list of applicationsapplications:-   #  First appname: app1    kind: nodejs    path: app1    exec:        platforms: k8s        builder: test-   # Second appname: app2    kind: golang    path: app2    exec:        platform: dockerh        builder: test


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5086879.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-16
下一篇2022-11-16

发表评论

登录后才能评论

评论列表(0条)

    保存