登录
首页 >  Golang >  Go问答

扩展 go-yaml 以自定义标签

来源:stackoverflow

时间:2024-02-28 22:39:23 122浏览 收藏

一分耕耘,一分收获!既然都打开这篇《扩展 go-yaml 以自定义标签》,就坚持看下去,学下去吧!本文主要会给大家讲到等等知识点,如果大家对本文有好的建议或者看到有不足之处,非常欢迎大家积极提出!在后续文章我会继续更新Golang相关的内容,希望对大家都有所帮助!

问题内容

我花了一些时间阅读 go-yaml 的代码和文档,但除了分叉项目之外,我还没有找到任何方法来做到这一点。

我想扩展 YAML 解组器,以便它可以接受自定义 YAML 标记(在本例中为 !包括 ),这反过来又允许我添加对包含文件的支持。这可以使用其他 YAML 库轻松实现,如本答案所示。

有没有办法使用库(或另一个 yaml 库)的公共接口来完成此任务?


解决方案


是的,这是可能的(因为 v3)。您可以将整个 yaml 文件加载到 yaml.node 中,然后遍历该结构。诀窍在于 yaml.node 是一种中间表示形式,只有定义解组器时才能访问它。 例如:

package main

import (
  "errors"
  "fmt"
  "io/ioutil"
  "gopkg.in/yaml.v3"
)

// used for loading included files
type Fragment struct {
  content *yaml.Node
}

func (f *Fragment) UnmarshalYAML(value *yaml.Node) error {
  var err error
  // process includes in fragments
  f.content, err = resolveIncludes(value)
  return err
}

type IncludeProcessor struct {
  target interface{}
}

func (i *IncludeProcessor) UnmarshalYAML(value *yaml.Node) error {
  resolved, err := resolveIncludes(value)
  if err != nil {
    return err
  }
  return resolved.Decode(i.target)
}

func resolveIncludes(node *yaml.Node) (*yaml.Node, error) {
  if node.Tag == "!include" {
    if node.Kind != yaml.ScalarNode {
      return nil, errors.New("!include on a non-scalar node")
    }
    file, err := ioutil.ReadFile(node.Value)
    if err != nil {
      return nil, err
    }
    var f Fragment
    err = yaml.Unmarshal(file, &f)
    return f.content, err
  }
  if node.Kind == yaml.SequenceNode || node.Kind == yaml.MappingNode {
    var err error
    for i := range node.Content {
      node.Content[i], err = resolveIncludes(node.Content[i])
      if err != nil {
        return nil, err
      }
    }
  }
  return node, nil
}

type MyStructure struct {
  // this structure holds the values you want to load after processing
  // includes, e.g.
  Num int
}

func main() {
  var s MyStructure
  yaml.Unmarshal([]byte("!include foo.yaml"), &IncludeProcessor{&s})
  fmt.Printf("Num: %v", s.Num)
}

当文件 foo.yaml 存在且内容为 num: 42 时,代码会打印 num: 42

理论要掌握,实操不能落!以上关于《扩展 go-yaml 以自定义标签》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>