为了账号安全,请及时绑定邮箱和手机立即绑定

将 YAML 解组为有序映射

将 YAML 解组为有序映射

Go
泛舟湖上清波郎朗 2022-06-21 16:23:56
我正在尝试使用Go YAML v3解组以下 YAML 。model:  name: mymodel  default-children:  - payment  pipeline:    accumulator_v1:      by-type:        type: static        value: false      result-type:        type: static        value: 3    item_v1:      amount:        type: schema-path        value: amount      start-date:        type: schema-path        value: start-date在管道下是任意数量的有序项目。应该将其解组的结构如下所示:type PipelineItemOption struct {        Type string        Value interface{}}type PipelineItem struct {        Options map[string]PipelineItemOption}type Model struct {        Name string        DefaultChildren []string `yaml:"default-children"`        Pipeline orderedmap[string]PipelineItem    // "pseudo code"}这如何与 Golang YAML v3 一起使用?在 v2 中有 MapSlice,但在 v3 中没有了。
查看完整描述

2 回答

?
慕的地10843

TA贡献1785条经验 获得超8个赞

您声称编组到中间体yaml.Node是高度非通用的,但我真的不明白为什么。它看起来像这样:


package main


import (

    "fmt"

    "gopkg.in/yaml.v3"

)


type PipelineItemOption struct {

        Type string

        Value interface{}

}


type PipelineItem struct {

    Name string

        Options map[string]PipelineItemOption

}


type Pipeline []PipelineItem


type Model struct {

        Name string

        DefaultChildren []string `yaml:"default-children"`

        Pipeline Pipeline

}


func (p *Pipeline) UnmarshalYAML(value *yaml.Node) error {

    if value.Kind != yaml.MappingNode {

        return fmt.Errorf("pipeline must contain YAML mapping, has %v", value.Kind)

    }

    *p = make([]PipelineItem, len(value.Content)/2)

    for i := 0; i < len(value.Content); i += 2 {

        var res = &(*p)[i/2]

        if err := value.Content[i].Decode(&res.Name); err != nil {

            return err

        }

        if err := value.Content[i+1].Decode(&res.Options); err != nil {

            return err

        }

    }

    return nil

}



var input []byte = []byte(`

model:

  name: mymodel

  default-children:

  - payment


  pipeline:

    accumulator_v1:

      by-type:

        type: static

        value: false

      result-type:

        type: static

        value: 3


    item_v1:

      amount:

        type: schema-path

        value: amount

      start-date:

        type: schema-path

        value: start-date`)


func main() {

    var f struct {

        Model Model

    }

    var err error

    if err = yaml.Unmarshal(input, &f); err != nil {

        panic(err)

    }

    fmt.Printf("%v", f)

}


查看完整回答
反对 回复 2022-06-21
?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

对我来说,弄清楚v3期望什么而不是MapSlice. 与@flyx 的回答类似,yaml.Node树需要行走,尤其是它的[]Content.


map[string]interface{}这是一个提供更可重用和更整洁的有序的实用程序。(虽然它不像指定的问题那样受到限制。)


根据上面的结构,Pipeline一般重新定义:


type Model struct {

    Name string

    DefaultChildren []string `yaml:"default-children"`

    Pipeline *yaml.Node

}

使用实用程序 fn 遍历yaml.Node内容:


// fragment

var model Model

if err := yaml.Unmarshal(&model) ; err != nil {

    return err

}


om, err := getOrderedMap(model.Pipeline)

if err != nil {

    return err

}


for _,k := range om.Order {

    v := om.Map[k]

    fmt.Printf("%s=%v\n", k, v)

}

实用程序 fn:


type OrderedMap struct {

    Map map[string]interface{}

    Order []string

}


func getOrderedMap(node *yaml.Node) (om *OrderedMap, err error) {

    content := node.Content

    end := len(content)

    count := end / 2


    om = &OrderedMap{

        Map: make(map[string]interface{}, count),

        Order: make([]string, 0, count),

    }

    

    for pos := 0 ; pos < end ; pos += 2 {

        keyNode := content[pos]

        valueNode := content[pos + 1]


        if keyNode.Tag != "!!str" {

            err = fmt.Errorf("expected a string key but got %s on line %d", keyNode.Tag, keyNode.Line)

            return

        }


        var k string

        if err = keyNode.Decode(&k) ; err != nil {

            return

        }


        var v interface{}

        if err = valueNode.Decode(&v) ; err != nil {

            return

        }


        om.Map[k] = v

        om.Order = append(om.Order, k)

    }


    return

}


查看完整回答
反对 回复 2022-06-21
  • 2 回答
  • 0 关注
  • 196 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号