I am trying to read data in a YAML file which looks like this:
Category Name:
Task 1:
Name: Meeting
PM: 1
TC: 0
STC: 1
Optional: false
There can be multiple tasks in a category and multiple categories. I've originally been reading the YAML file like so.
type Task struct {
Name string
PM string
TC string
STC string
Optional bool
}
type Category struct {
Name string
Tasks []Task
}
func parseFile() map[string]map[string]map[string]string {
file, err := ioutil.ReadFile("config.yaml")
if err != nil {
log.Fatal(err)
}
data := make(map[string]map[string]map[string]string)
err1 := yaml.Unmarshal(file, &data)
if err1 != nil {
log.Fatal(err1)
}
return data
}
Then I just have a function to loop through the map created in parseFile() and create a list of Category with the filled in information. This works great... other than the fact that the order of categories/tasks written in the YAML file is not preserved because of maps not being ordered.
From reading online, I found that you can preserve the order using yaml.MapSlice{} from gokpg.in/yaml.v2. However, I have no idea what to do with this resulting MapSlice. I can iterate through it to get the categories but I can't iterate through the .Value since MapItems are interfaces, but MapItems would store my list of tasks. What can I do so I can do so I can get the tasks and put in a []Task?
Help is appreciated :)
CodePudding user response:
I managed to solve this by changing the format of my YAML and structures, then unmarshalling directly into the structure.
The new structs.
type Categories struct {
Category []struct {
Name string `yaml:"CategoryName"`
Task []struct {
Name string `yaml:"TaskName"`
PM float64 `yaml:"PM"`
TC float64 `yaml:"TC"`
STC float64 `yaml:"STC"`
Optional bool `yaml:"Optional"`
} `yaml:"Tasks"`
} `yaml:"Categories"`
}
The new format for the YAML file to support what's in the struct.
Categories:
- CategoryName: Category 1
Tasks:
- TaskName: Test 1
PM: 1
TC: 0
STC: 1
Optional: false
- TaskName: Test 2
PM: 2
TC: 0
STC: 2
Optional: false
- CategoryName: Category 2
Tasks:
- TaskName: Test 3
PM: 1
TC: 2
STC: 3
Optional: true
Unmarshalling the YAML file directly into a new struct
var tasks Categories
file, err := ioutil.ReadFile("config.yaml")
if err != nil {
log.Fatal(err)
}
yaml.Unmarshal(file, &tasks)
This worked to fix my problem - no longer using maps so the order is preserved and using the structs in a way that I find easy to loop through.