Json 修改现有yaml文件并添加新数据和注释

Json 修改现有yaml文件并添加新数据和注释,json,go,yaml,abstract-syntax-tree,Json,Go,Yaml,Abstract Syntax Tree,我最近看到go库有了新版本(V3) 有了这些功能(我认为这是一个致命的特性:)),它可以帮助修改YAML,而不改变文件的结构 但是由于它是相当新的(从上周开始),我没有找到一些有用的文档和我需要的上下文的示例(添加新的对象/节点,保持文件结构不变,而不删除注释等) 我需要的是操作yaml文件 比如说 我有这个山药档案 version: 1 type: verbose kind : bfr # my list of applications applications: - name: app

我最近看到go库有了新版本(V3)

有了这些功能(我认为这是一个致命的特性:)),它可以帮助修改YAML,而不改变文件的结构

但是由于它是相当新的(从上周开始),我没有找到一些有用的文档和我需要的上下文的示例(添加新的对象/节点,保持文件结构不变,而不删除注释等)

我需要的是操作yaml文件

比如说

我有这个山药档案

version: 1
type: verbose
kind : bfr

# my list of applications
applications:
  - name: app1
    kind: nodejs
    path: app1
    exec:
      platforms: k8s
      builder: test
现在我得到了一个json对象(例如带有
app2
),我需要将其插入到现有文件中

[

    {
        "comment: "Second app",
        "name": "app2",
        "kind": "golang",
        "path": "app2",
        "exec": {
            "platforms": "dockerh",
            "builder": "test"
        }
    }
]
我需要在第一个应用程序之后将其添加到yml文件中,(应用程序是应用程序的数组)

是否可以从yaml文件中添加新的json对象?同时删除现有的

我也找到了这个博客

这是表示对象的类型

type VTS struct {
    version string       `yaml:"version"`
    types   string       `yaml:"type"`
    kind    string       `yaml:"kind,omitempty"`
    apps    Applications `yaml:"applications,omitempty"`
}

type Applications []struct {
    Name string `yaml:"name,omitempty"`
    Kind string `yaml:"kind,omitempty"`
    Path string `yaml:"path,omitempty"`
    Exec struct {
        Platforms string `yaml:"platforms,omitempty"`
        Builder   string `yaml:"builder,omitempty"`
    } `yaml:"exec,omitempty"`
}
更新

在测试了
wiil7200提供的解决方案后,我发现了两个问题

我最后用它来写文件
err=ioutil.WriteFile(“output.yaml”,b,0644)

yaml输出有2个问题

  • 应用程序的数组是从注释开始的,它应该 从名字开始

  • 名称
    条目之后,将显示
    种类
    属性和之后的所有其他属性 未与
    名称对齐

  • 你知道如何解决这些问题吗?关于
    注释
    问题,假设我是从其他属性获得的 而不是来自json(如果它使它更简单的话)


    首先,让我先说使用yaml.Node在从有效的yaml进行编组时不会生成有效的yaml,如下例所示。可能应该提出一个问题

    主程序包
    进口(
    “fmt”
    “日志”
    “gopkg.in/yaml.v3”
    )
    变量(
    sourceYaml=`版本:1
    类型:详细
    种类:bfr
    #我的申请表
    应用:
    #第一个应用程序
    -名称:app1
    种类:nodejs
    路径:app1
    执行官:
    平台:k8s
    建造商:测试
    `
    )
    func main(){
    t:=yaml.Node{}
    错误:=yaml.Unmarshal([]字节(sourceYaml),&t)
    如果错误!=零{
    log.Fatalf(“错误:%v”,错误)
    }
    b、 错误:=yaml.Marshal(&t)
    如果错误!=零{
    log.Fatal(错误)
    }
    格式打印项次(字符串(b))
    }
    
    在go版本go1.12.3 windows/amd64中生成以下无效yaml

    version: 1
    type: verbose
    kind: bfr
    
    
    # my list of applications
    applications:
    -   #  First app
    name: app1
        kind: nodejs
        path: app1
        exec:
            platforms: k8s
            builder: test
    

    其次,使用结构,例如

    类型VTS结构{
    版本字符串`yaml:“版本”json:“版本”`
    类型字符串`yaml:“类型”json:“类型”`
    种类字符串`yaml:“种类,省略空”json:“种类,省略空”`
    Apps yaml.Node`yaml:“应用程序,省略空”json:“应用程序,省略空”`
    }
    
    从ubuntu的博客和源代码文档来看,它似乎可以正确识别结构中作为节点的字段,并单独构建树,但事实并非如此。 当解组时,它将给出一个正确的节点树,但当重新组时,它将生成以下yaml,其中包含yaml.node公开的所有字段。遗憾的是,我们不能走这条路,必须找到另一条路

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

    忽略结构中yaml.Nodes的第一个问题和封送错误(在gopkg.in/yaml.v3.0.0-20190409140830-cdc409dda467上),我们现在可以开始操作包公开的节点。不幸的是,没有一种抽象可以轻松地添加节点,因此使用可能会有所不同,而识别节点可能是一件痛苦的事情。反思在这里可能有点帮助,所以我把它留给你们作为练习

    您将发现comment spew.Dumps以一种很好的格式转储整个节点树,这有助于在将节点添加到源树时进行调试

    当然,您也可以删除节点,您只需要确定需要删除哪些特定节点。如果父节点是一个映射或序列,您只需确保删除它

    主程序包
    进口(
    “编码/json”
    “fmt”
    “日志”
    “gopkg.in/yaml.v3”
    )
    变量(
    sourceYaml=`版本:1
    类型:详细
    种类:bfr
    #我的申请表
    应用:
    #第一个应用程序
    -名称:app1
    种类:nodejs
    路径:app1
    执行官:
    平台:k8s
    建造商:测试
    `
    modifyJsonSource=`
    [
    {
    “评论”:“第二个应用程序”,
    “名称”:“app2”,
    “善良”:“戈朗”,
    “路径”:“app2”,
    “执行官”:{
    “平台”:“dockerh”,
    “生成器”:“测试”
    }
    }
    ]
    `
    )
    //悉尼威立雅运输公司需要公开字段,否则解组将不会填充未报告的字段。
    类型VTS结构{
    版本字符串`yaml:“版本”json:“版本”`
    类型字符串`yaml:“类型”json:“类型”`
    种类字符串`yaml:“种类,省略空”json:“种类,省略空”`
    Apps Applications`yaml:“Applications,ommitempty”json:“Applications,ommitempty”`
    }
    类型应用程序[]结构{
    名称字符串`yaml:“名称,省略空”json:“名称,省略空”`
    种类字符串`yaml:“种类,省略空”json:“种类,省略空”`
    路径字符串`yaml:“路径,省略空”json:“路径,省略空”`
    执行结构{
    平台字符串`yaml:“平台,省略空”json:“平台,省略空”`
    生成器字符串`yaml:“生成器,省略空”json:“生成器,省略空”`
    }`yaml:“exec,ommitempty”json:“exec,ommitempty”`
    注释字符串`yaml:“注释,省略空”json:“注释,省略空”`
    }
    func main(){
    t:=yaml.Node{}
    错误:=yaml.Unmarshal([]字节(sourceYaml),&t)
    如果错误!=零{
    log.Fatalf(“错误:%v”,错误)
    }
    //查找包含项的seq数组的Map节点
    applicationNode:=迭代节点(&t,“应用程序”)
    //转储(iterateNode(&t,“应用程序”))
    var addFromJson应用程序
    err=json.Unmarshal([]字节(modifyJsonSource),&addFromJson)
    如果错误!=零{
    原木,肥肉
    
    version: 1
    type: verbose
    kind: bfr
    
    
    # my list of applications
    applications:
    -   #  First app
    name: app1
        kind: nodejs
        path: app1
        exec:
            platforms: k8s
            builder: test
    
    version: "1"
    type: verbose
    kind: bfr
    applications:
        kind: 2
        style: 0
        tag: '!!seq'
        value: ""
        anchor: ""
        alias: null
        content:
        -   #  First app
    name: app1
            kind: nodejs
            path: app1
            exec:
                platforms: k8s
                builder: test
        headcomment: ""
        linecomment: ""
        footcomment: ""
        line: 9
        column: 3
    
    version: 1
    type: verbose
    kind: bfr
    
    
    # my list of applications
    applications:
    -   #  First app
    name: app1
        kind: nodejs
        path: app1
        exec:
            platforms: k8s
            builder: test
    -   # Second app
    name: app2
        kind: golang
        path: app2
        exec:
            platform: dockerh
            builder: test