亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

將 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 關注
  • 183 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號