如何解析yaml并为接口深层结构获取价值

时间:2019-03-06 10:44:00

标签: go yaml

我正在尝试解析此Yaml,并且我想获取values条目(test1或test2)的run而不成功,这是我的工作示例。

我有点迷失于map :(, 这是给我可以改变的yaml ...

知道如何获得这些值

package main

import (
    "fmt"
    "log"

    "gopkg.in/yaml.v2"
)

var runContent = []byte(`
version: "3.2"

run-parameters:
  before:
    run-parameters:
      run: test1

  after:
    run-parameters:
      run: test2

`)

type FTD struct {
    Version     string     `yaml:"version,omitempty"`
    BuildParams *RunParams `yaml:"run-parameters,omitempty"`
}

type RunParams struct {
    BeforeExec map[string]interface{} `yaml:"before,omitempty"`
    AfterExec map[string]interface{} `yaml:"after,omitempty"`
}

func main() {
    runners := &FTD{}
    // parse mta yaml
    err := yaml.Unmarshal(runContent, runners)
    if err != nil {
        log.Fatalf("Error : %v", err)
    }
    for k, v := range runners.BuildParams.BeforeExec {
        fmt.Println(k, v.(interface{}))
    }
}

这是工作示例 https://play.golang.org/p/qTqUJy3md0c

我也尝试过

这有效

run := runners.BuildParams.BeforeExec["run-parameters"].(map[interface{}]interface{})["run"]
     fmt.Println("run: ", run)

我尝试过的是可行的,但是如果run值为空或根本没有任何条目怎么办,这将导致转储,我该如何克服呢?

1 个答案:

答案 0 :(得分:1)

  

我尝试过的是可以正常工作的,但是如果运行值为空或根本没有条目怎么办,这将导致转储,我该如何克服呢?

您可以

runParams, ok := runners.BuildParams.BeforeExec["run-parameters"]

if !ok {
    // handle lack of "run-parameters" in BeforeExec
}

runParamsMap, ok := runParams.(map[interface{}]interface{})

if !ok {
    // handle "run-parameters" not being a map
}

run, ok := runParamsMap["run"]

if !ok {
    // handle lack of "run" inside "run-parameters"
}

runStr, ok := run.(string)

if !ok {
    // handle "run" not being a string
}

fmt.Println("run: ", runStr)

这很冗长,因此您可以使用类似https://github.com/jmoiron/jsonq的名称,您可以在其中指定嵌套在多个地图级别中的所需值的“路径”。尽管名称中带有“ json”,该库仍可使用map [string] interface {}而不是json文件。但是请注意,用于yaml解组的库将以map[interface{}]interface{}而不是map[string]interface{}的形式出现,并且您必须使用其他库才能使其与jsonq一起使用。

run, err := jsonq.NewQuery(runners.BuildParams.BeforeExec).String("run-parameters", "run")

if err != nil {
    // handle all possible errors in one place
}

fmt.Println("run: ", run)