英文:
Preserving order in YAML file in Go
问题
我正在尝试读取一个 YAML 文件中的数据,它的格式如下:
Category Name:
Task 1:
Name: Meeting
PM: 1
TC: 0
STC: 1
Optional: false
一个类别中可以有多个任务,而且可以有多个类别。我最初是这样读取 YAML 文件的。
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
}
然后,我只需在 parseFile() 创建的映射中循环,并使用填充的信息创建一个 Category 列表。这个方法很好用... 除了一个问题,由于映射不是有序的,所以无法保留 YAML 文件中类别/任务的顺序。
从网上的资料中,我发现可以使用 gokpg.in/yaml.v2 中的 yaml.MapSlice{} 来保留顺序。然而,我不知道如何处理得到的 MapSlice。我可以遍历它以获取类别,但无法遍历 .Value,因为 MapItems 是接口类型,而 MapItems 将存储我的任务列表。我应该怎么做才能获取任务并放入 []Task 中呢?
谢谢帮助
英文:
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
答案1
得分: 0
我通过更改我的YAML和结构的格式,然后直接解组到结构中来解决了这个问题。
新的结构体如下:
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"`
}
YAML文件的新格式以支持结构体中的内容如下:
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
将YAML文件直接解组到新的结构体中:
var tasks Categories
file, err := ioutil.ReadFile("config.yaml")
if err != nil {
log.Fatal(err)
}
yaml.Unmarshal(file, &tasks)
这样做可以解决我的问题——不再使用映射,因此顺序得到保留,并且以我认为易于循环遍历的方式使用结构体。
英文:
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.
答案2
得分: 0
package main
import (
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
"log"
)
type Config struct {
CategoryName []map[string]Task `yaml:"CategoryName"`
}
type Task struct {
Name string `yaml:"Name"`
PM int `yaml:"PM"`
TC int `yaml:"TC"`
STC int `yaml:"STC"`
Optional bool `yaml:"Optional"`
}
func main() {
yamlData := []byte(`
CategoryName:
- Task1:
Name: "Meeting"
PM: 1
TC: 0
STC: 1
Optional: false
- Task2:
Name: "Meeting v2"
PM: 2
TC: 0
STC: 2
Optional: false
`)
var config Config
err := yaml.Unmarshal(yamlData, &config)
if err != nil {
log.Fatalf("Erreur lors de la décomposition du YAML : %v", err)
}
fmt.Printf("Configuration : %+v\n", config)
}
以上是要翻译的代码部分。
英文:
package main
import (
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
"log"
)
type Config struct {
CategoryName []map[string]Task `yaml:"CategoryName"`
}
type Task struct {
Name string `yaml:"Name"`
PM int `yaml:"PM"`
TC int `yaml:"TC"`
STC int `yaml:"STC"`
Optional bool `yaml:"Optional"`
}
func main() {
yamlData := []byte(`
CategoryName:
- Task1:
Name: "Meeting"
PM: 1
TC: 0
STC: 1
Optional: false
- Task2:
Name: "Meeting v2"
PM: 2
TC: 0
STC: 2
Optional: false
`)
var config Config
err := yaml.Unmarshal(yamlData, &config)
if err != nil {
log.Fatalf("Erreur lors de la décomposition du YAML : %v", err)
}
fmt.Printf("Configuration : %+v\n", config)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论