Golang从yaml文件中提取值


jobs:
- name: test
public: true
plan:
- try:
task: task1
file: test1.yaml
on_success:
in_parallel:
steps:
- task: task2
file: test2.yaml
- task: task3
file: task3.yaml

我想从这个yaml中提取task的值。这很棘手,因为它可能位于文件中的不同路径。除了上述task可以在yaml文件中找到之外,还有一些不同的路径。有没有一种简单的方法可以提取task的所有值?我应该转换为json吗?

go yaml希望您定义一个目标类型和该类型的解组器。

如果您想使用关键字task提取某个映射中的所有值,那么您的类型将是任务名称列表。

对于该类型,您需要创建一个解组器函数,该函数获取YAML文件的根节点,并将任务名称提取到您定义的类型的对象中。

下面是一个最小的工作示例:

package main
import (
"errors"
"fmt"
"gopkg.in/yaml.v3"
)
type Tasks struct {
items []string
}
// descend implements recursive descent into YAML mapping and sequence structures
func (t *Tasks) descend(node *yaml.Node) error {
switch node.Kind {
case yaml.SequenceNode:
for _, item := range(node.Content) {
t.descend(item)
}
case yaml.MappingNode:
for i := 0; i < len(node.Content); i += 2 {
key := node.Content[i]
value := node.Content[i+1]
if key.Kind != yaml.ScalarNode ||
key.Value != "task" {
t.descend(value)
continue
}
if value.Kind != yaml.ScalarNode {
return errors.New("encountered non-scalar task")
}
t.items = append(t.items, value.Value)
}
}
return nil
}
// UnmarshalYAML is the unmarshaler that will be called by the YAML processor.
func (t *Tasks) UnmarshalYAML(value *yaml.Node) error {
t.items = nil
return t.descend(value)
}

func main() {
var t Tasks
// I fixed some whitespace issues in your YAML input
if err := yaml.Unmarshal([]byte(`jobs:
- name: test
public: true
plan:
- try:
task: task1
file: test1.yaml
on_success:
in_parallel:
steps:
- task: task2
file: test2.yaml
- task: task3
file: task3.yaml`), &t); err != nil {
panic(err)
}
for _, item := range(t.items) {
fmt.Println(item)
}
}

输出:

task1
task2
task3

请注意,此解决方案通常不正确,因为YAML节点可能包含循环(由于YAML锚/别名(,这将导致堆栈溢出,因为代码不检查循环。

最新更新