【问题标题】:Error while parsing yaml in golang在 golang 中解析 yaml 时出错
【发布时间】:2019-01-23 11:51:13
【问题描述】:

我有一个类似以下的 yaml,我需要使用 go 解析它。 当我尝试使用解析运行代码时,出现错误。 下面是代码:

var runContent= []byte(`

- runners:
   - name: function1
     type: func1
      - command: spawn child process
      - command: build
      - command: gulp

  - name: function1
    type: func2
      - command: run function 1
  - name: function3
    type: func3
      - command: ruby build

  - name: function4
    type: func4
      - command: go build 

`)

这些是类型:

type Runners struct {

    runners string `yaml:"runners"`
        name string `yaml:”name”`
        Type: string  `yaml: ”type”`
        command  [] Command 
}


type Command struct {
    command string `yaml: ”command”`
}



runners := Runners{}
err = yaml.Unmarshal(runContent, &runners)
if err != nil {
    log.Fatalf("Error : %v", err)
}

当我尝试解析它时,我收到一个错误invalid map,这里可能缺少什么?

【问题讨论】:

  • 在 Go 中,您必须导出所有结构字段以进行编组/解组!
  • 另外,从规范来看,您的结构从这里看起来不太好。
  • YAML 文档中的缩进不正确,与 Go 类型不匹配。 type 可以是字符串、列表或映射。选一个。您还在 struct 标签中混合了 ASCII 和 unicode 引号。仅使用 ASCII。
  • 您有一些“智能引号”,例如在这里:yaml:”name”。如果这些在您的实际代码中(而不仅仅是此 StackOverflow sn-p 中的复制/粘贴事故),那么这会给您带来某种麻烦。

标签: go struct yaml


【解决方案1】:

您发布的代码包含多个错误,包括结构字段Type。您的代码中提供的 yaml 无效。这将导致在将 yaml 解组为 struct 时出错。

在go中解组yaml时,要求:

解码值的类型应与 各自的值。如果一个或多个值由于无法解码 对于类型不匹配,解码部分继续,直到结束 YAML 内容,并返回一个 *yaml.TypeError 以及详细信息 所有遗漏的值。

除此之外:

结构字段仅在导出时才被解组(具有 大写首字母),并使用字段名称进行解组 小写作为默认键。

在定义yaml 标记时也存在错误,其中包含空格。自定义键可以通过字段标签中的“yaml”名称定义:第一个逗号之前的内容用作键。

type Runners struct {

    runners string `yaml:"runners"` // fields should be exportable
        name string `yaml:”name”`
        Type: string  `yaml: ”type”` // tags name should not have space in them.
        command  [] Command 
} 

要使结构可导出,将结构和字段转换为大写首字母并删除 yaml 标记名称中的空格:

type Runners struct {
    Runners string `yaml:"runners"`
    Name string `yaml:"name"`
    Type string `yaml:"type"`
    Command  []Command 
}

type Command struct {
    Command string `yaml:"command"`
}

修改如下代码使其生效。

package main

import (
    "fmt"
    "log"

    "gopkg.in/yaml.v2"
)

var runContent = []byte(`
- runners:
  - name: function1
    type:
    - command: spawn child process
    - command: build
    - command: gulp
  - name: function1
    type:
    - command: run function 1
  - name: function3
    type:
    - command: ruby build
  - name: function4
    type:
    - command: go build
`)

type Runners []struct {
    Runners []struct {
        Type []struct {
            Command string `yaml:"command"`
        } `yaml:"type"`
        Name string `yaml:"name"`
    } `yaml:"runners"`
}

func main() {

    runners := Runners{}
    // parse mta yaml
    err := yaml.Unmarshal(runContent, &runners)
    if err != nil {
        log.Fatalf("Error : %v", err)
    }
    fmt.Println(runners)
}

Playground example

在此处在线验证您的 yaml https://codebeautify.org/yaml-validator/cb92c85b

【讨论】:

  • 谢谢,在你的例子中你使用 json,为什么?
  • @RaynD 没有我用过提供的 yaml 只是更改格式以验证相同。
  • @RaynD 只需使用我编写的代码并将其与您的代码进行比较,以检查您的代码有什么问题。我的一个正在工作,它正在使用 yaml。只是我首先验证了您的代码中错误的 yaml。
  • 谢谢,当我这样检查时,它不起作用,为什么? (我使用了你建议的结构)play.golang.org/p/nHGui7xZG7V
  • 错误是:cannot unmarshal !!seq into main.Runners
猜你喜欢
  • 2018-12-21
  • 2011-08-28
  • 2017-04-30
  • 1970-01-01
  • 1970-01-01
  • 2012-05-15
  • 2023-03-19
  • 2015-11-15
  • 2013-08-18
相关资源
最近更新 更多