流式YAML解析中如何对当前文档进行两次解码?
流式YAML解析中如何对当前文档进行两次解码?
这个问题我之前也碰到过,核心痛点就是yaml.Decoder的Decode方法每次调用都会“消费”掉当前文档的内容,直接连续调用两次的话,第二次就会跳到下一个文档了。给你个简单靠谱的解决思路:先把当前文档完整解析成一个yaml.Node节点,之后你就可以对这个节点反复解码,想转成什么结构体都行,完全不会影响后续文档的解析~
具体修改后的代码示例如下:
package main import ( "errors" "fmt" "io" "os" "gopkg.in/yaml.v3" ) type Spec struct { Name string `yaml:"name"` } type Special struct { Integer string `yaml:"integer"` } func main() { f := os.Stdin d := yaml.NewDecoder(f) for { // 第一步:把当前完整文档解析为yaml.Node,这一步仅读取当前文档,不会移动到下一个 var node yaml.Node err := d.Decode(&node) if errors.Is(err, io.EOF) { break } if err != nil { panic(err) } // 第一次解码:从Node中解析出Spec,拿到name字段 var spec Spec if err := node.Decode(&spec); err != nil { panic(err) } fmt.Printf("name is '%s'\n", spec.Name) // 根据name判断,决定用哪个结构体再次解码当前文档 if spec.Name == "special" { var special Special if err := node.Decode(&special); err != nil { panic(err) } fmt.Printf("special integer value: '%s'\n", special.Integer) } // 这里可以扩展其他name对应的结构体解析逻辑 } }
原理其实很简单:yaml.Node就像是当前YAML文档在内存中的完整快照,把文档读进Node之后,所有的解码操作都是在内存里对这个快照进行处理,完全不会触动yaml.Decoder的文档指针。不管你对Node调用多少次Decode,都只会解析同一个文档的内容,后续循环里再调用d.Decode(&node)时,才会读取下一个文档。
另外提个小细节:如果YAML文档里有某些字段在你要解析的结构体中不存在,yaml.Node的Decode方法会自动忽略这些字段,不用额外处理(除非你开启了严格解码模式)。
备注:内容来源于stack exchange,提问作者guettli
相关产品推荐
相关产品推荐

