Немаршалинг YAML на заказанные карты - PullRequest
0 голосов
/ 04 августа 2020

Я пытаюсь демаршалировать следующий YAML с помощью Go YAML v3 .

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.

1 Ответ

1 голос
/ 05 августа 2020

Вы утверждаете, что маршалинг на промежуточный yaml.Node не является универсальным c, но я действительно не понимаю почему. Выглядит это так:

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)
}
...