【问题标题】:How to unmarshal a yaml array?如何解组 yaml 数组?
【发布时间】:2021-08-10 09:21:54
【问题描述】:

我有下一个 yaml,如果我在 online yaml website 中验证它,它说它是有效的:

- {"foo": "1", "bar": "2"}

然后,我编写了一个代码来解析这个 yaml 中的值 12,如下所示:

test.go

package main
import "gopkg.in/yaml.v2"
import "fmt"

type Config struct {
    Foo string
    Bar string
}

type Configs struct {
    Cfgs []Config `foobar`
}

func main() {
    //var data = `
    //  foobar:
    //  - foo: 1
    //    bar: 2
    //`
    var data = `
      - foo: 1
        bar: 2
    `

    source := []byte("foobar:" + data)
    var configs Configs
    err := yaml.Unmarshal(source, &configs)
    if err != nil {
        fmt.Println("error: %v", err)
    }
    fmt.Printf("--- configs:\n%v\n\n", configs)
    fmt.Println(configs.Cfgs[0].Foo)
    fmt.Println(configs.Cfgs[0].Bar)
}

它可以像下一个一样工作:

shubuntu1@shubuntu1:~/20210810$ go run test.go
--- configs:
{[{1 2}]}

1
2

有什么问题?

你可以看到我在这里做了一个解决方法,在原始 yaml 之前添加特殊的 foobar 键,然后我可以使用 type Configs struct 来解组它:

来自

- foo: 1
  bar: 2

foobar:
- foo: 1
  bar: 2

那么,如果我不使用变通方法添加前缀foobar:,我怎么能直接解析- {"foo": 1, "bar": 2}

【问题讨论】:

    标签: go yaml


    【解决方案1】:

    由于您的 YAML 数据是一个数组,请将其解组为 Config 结构的数组。

    package main
    
    import (
        "fmt"
    
        "gopkg.in/yaml.v2"
    )
    
    type Config struct {
        Foo string
        Bar string
    }
    
    func main() {
        var configs []Config
    
        var data = `
          - foo: 1
            bar: 2
        `
    
        err := yaml.Unmarshal([]byte(data), &configs)
        if err != nil {
            panic(err)
        }
    
        fmt.Println(configs)
    }
    
    

    输出:

    [{1 2}]
    

    试穿-Go Playground

    【讨论】:

    • 太好了,这么简单的解决方案我错过了,谢谢~
    【解决方案2】:

    既然问题已经回答了,我想我可以在讨论中添加一些内容:

        var data = `
          - foo: 1
            bar: 2
        `
    

    此处的数据变量,您编写它的方式,在每行的开头包含缩进。

    此处的额外缩进将与所有实际的 yaml 数据一起传递到 yaml.Unmarshal(),这可能会使事情变得混乱,因为 gofmt 格式化您的代码以使用 TAB 作为缩进TAB yaml 中禁止缩进 (https://stackoverflow.com/a/19976827/7509248)。

    如果你在 yaml 中使用制表符作为缩进,在尝试解组时会抛出这样的错误:

    yaml: line 1: found a tab character that violates indentation
    

    最好从单独的文件加载data 以避免此类问题。

    package main
    
    import (
        "fmt"
        "io/ioutil"
    
        "gopkg.in/yaml.v2"
    )
    
    type Config struct {
        Foo string
        Bar string
    }
    
    func main() {
        var configs []Config
    
        source, err := ioutil.ReadFile("config.yaml")
        if err != nil {
            fmt.Printf("failed reading config file: %v\n", err)
        }
    
        err = yaml.Unmarshal(source, &configs)
        if err != nil {
            fmt.Printf("error: %v\n", err)
        }
    
        fmt.Printf("config:\n%+v\n", configs)
    }
    

    config.yaml:

    - foo: 1
      bar: 2
    

    输出:

    config:
    [{Foo:1 Bar:2}]
    

    【讨论】:

    • echo -e "func main() {\n t := `\n foo`\n}" | gofmt | tr ' \t' '•↹' 表明 gofmt not 替换了反引号字符串内的空格缩进,所以这不是问题。此外,最好将输入放在 StackOverflow 问题的代码示例中,这样其他人就不需要设置文件系统来执行代码。
    猜你喜欢
    • 2020-08-03
    • 2015-05-14
    • 2015-05-14
    • 2021-03-13
    • 1970-01-01
    • 2014-07-28
    • 1970-01-01
    • 2021-06-05
    相关资源
    最近更新 更多