2 回答
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)
}
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
}
- 2 回答
- 0 关注
- 196 浏览
添加回答
举报
