Reputation: 1417
Let's say I have the following yaml file:
key1:
- "Value1"
- "Value2"
key2:
- "Value3"
- "Value4"
And I want to unmarshal that in Go. I can let Go decide what the scheme should look like and print it out.
m := make(map[interface{}]interface{})
err := yaml.Unmarshal(yaml_file, &m)
fmt.Prinf(m)
This will print something like this:
map[key1:[Value1 Value2] key2:[Value3 Value4]]
But maps are unordered. The order is very important for me tho and I also don't want to loose the keys.
I can't just create a struct and try to unmarshal the yaml file to a slice of that struct...
type Element struct {
Key string
Value interface{}
}
t := []Element{}
err := yaml.Unmarshal(yaml_file, &t)
if err != nil {
log.Fatalf("error: %v", err)
}
Will print error: yaml: unmarshal errors: line 2: cannot unmarshal !!map into []Element
There is no field tag to tell the yaml parser to fill the Key property with the yaml key.
Is there a different way than writing my own decoder?
Upvotes: 3
Views: 4797
Reputation: 1417
Just found the answer right before I wanted to post the question.
The answer is MapSlice!
You need to import yaml.v2
from gopkg
. (As of writing this MapSlices don't seem to be implemented in yaml.v3 yet)
MapSlices
implement exactly what I needed and are made of a number of MapItem
s.
type MapItem struct {
Key, Value interface{}
}
So now just unmarshal to a MapSlice. If you want to work with your own types you can always convert it but might need to do some typecasting.
m := yaml.MapSlice{}
yaml.Unmarshal(yaml_file, &m)
t := []Element{}
for _, item := range m {
t = append(t, Element{item.Key.(string), item.Value})
}
Upvotes: 6