在Go语言中保留YAML文件的顺序

huangapple go评论116阅读模式
英文:

Preserving order in YAML file in Go

问题

我正在尝试读取一个 YAML 文件中的数据,它的格式如下:

  1. Category Name:
  2. Task 1:
  3. Name: Meeting
  4. PM: 1
  5. TC: 0
  6. STC: 1
  7. Optional: false

一个类别中可以有多个任务,而且可以有多个类别。我最初是这样读取 YAML 文件的。

  1. type Task struct {
  2. Name string
  3. PM string
  4. TC string
  5. STC string
  6. Optional bool
  7. }
  1. type Category struct {
  2. Name string
  3. Tasks []Task
  4. }
  1. func parseFile() map[string]map[string]map[string]string {
  2. file, err := ioutil.ReadFile("config.yaml")
  3. if err != nil {
  4. log.Fatal(err)
  5. }
  6. data := make(map[string]map[string]map[string]string)
  7. err1 := yaml.Unmarshal(file, &data)
  8. if err1 != nil {
  9. log.Fatal(err1)
  10. }
  11. return data
  12. }

然后,我只需在 parseFile() 创建的映射中循环,并使用填充的信息创建一个 Category 列表。这个方法很好用... 除了一个问题,由于映射不是有序的,所以无法保留 YAML 文件中类别/任务的顺序。

从网上的资料中,我发现可以使用 gokpg.in/yaml.v2 中的 yaml.MapSlice{} 来保留顺序。然而,我不知道如何处理得到的 MapSlice。我可以遍历它以获取类别,但无法遍历 .Value,因为 MapItems 是接口类型,而 MapItems 将存储我的任务列表。我应该怎么做才能获取任务并放入 []Task 中呢?

谢谢帮助 在Go语言中保留YAML文件的顺序

英文:

I am trying to read data in a YAML file which looks like this:

  1. Category Name:
  2. Task 1:
  3. Name: Meeting
  4. PM: 1
  5. TC: 0
  6. STC: 1
  7. Optional: false

There can be multiple tasks in a category and multiple categories. I've originally been reading the YAML file like so.

  1. type Task struct {
  2. Name string
  3. PM string
  4. TC string
  5. STC string
  6. Optional bool
  7. }
  1. type Category struct {
  2. Name string
  3. Tasks []Task
  4. }
  1. func parseFile() map[string]map[string]map[string]string {
  2. file, err := ioutil.ReadFile("config.yaml")
  3. if err != nil {
  4. log.Fatal(err)
  5. }
  6. data := make(map[string]map[string]map[string]string)
  7. err1 := yaml.Unmarshal(file, &data)
  8. if err1 != nil {
  9. log.Fatal(err1)
  10. }
  11. return data
  12. }

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 在Go语言中保留YAML文件的顺序

答案1

得分: 0

我通过更改我的YAML和结构的格式,然后直接解组到结构中来解决了这个问题。

新的结构体如下:

  1. type Categories struct {
  2. Category []struct {
  3. Name string `yaml:"CategoryName"`
  4. Task []struct {
  5. Name string `yaml:"TaskName"`
  6. PM float64 `yaml:"PM"`
  7. TC float64 `yaml:"TC"`
  8. STC float64 `yaml:"STC"`
  9. Optional bool `yaml:"Optional"`
  10. } `yaml:"Tasks"`
  11. } `yaml:"Categories"`
  12. }

YAML文件的新格式以支持结构体中的内容如下:

  1. Categories:
  2. - CategoryName: Category 1
  3. Tasks:
  4. - TaskName: Test 1
  5. PM: 1
  6. TC: 0
  7. STC: 1
  8. Optional: false
  9. - TaskName: Test 2
  10. PM: 2
  11. TC: 0
  12. STC: 2
  13. Optional: false
  14. - CategoryName: Category 2
  15. Tasks:
  16. - TaskName: Test 3
  17. PM: 1
  18. TC: 2
  19. STC: 3
  20. Optional: true

将YAML文件直接解组到新的结构体中:

  1. var tasks Categories
  2. file, err := ioutil.ReadFile("config.yaml")
  3. if err != nil {
  4. log.Fatal(err)
  5. }
  6. 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.

  1. type Categories struct {
  2. Category []struct {
  3. Name string `yaml:"CategoryName"`
  4. Task []struct {
  5. Name string `yaml:"TaskName"`
  6. PM float64 `yaml:"PM"`
  7. TC float64 `yaml:"TC"`
  8. STC float64 `yaml:"STC"`
  9. Optional bool `yaml:"Optional"`
  10. } `yaml:"Tasks"`
  11. } `yaml:"Categories"`
  12. }

The new format for the YAML file to support what's in the struct.

  1. Categories:
  2. - CategoryName: Category 1
  3. Tasks:
  4. - TaskName: Test 1
  5. PM: 1
  6. TC: 0
  7. STC: 1
  8. Optional: false
  9. - TaskName: Test 2
  10. PM: 2
  11. TC: 0
  12. STC: 2
  13. Optional: false
  14. - CategoryName: Category 2
  15. Tasks:
  16. - TaskName: Test 3
  17. PM: 1
  18. TC: 2
  19. STC: 3
  20. Optional: true

Unmarshalling the YAML file directly into a new struct

  1. var tasks Categories
  2. file, err := ioutil.ReadFile("config.yaml")
  3. if err != nil {
  4. log.Fatal(err)
  5. }
  6. 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

  1. package main
  2. import (
  3. "fmt"
  4. "gopkg.in/yaml.v2"
  5. "io/ioutil"
  6. "log"
  7. )
  8. type Config struct {
  9. CategoryName []map[string]Task `yaml:"CategoryName"`
  10. }
  11. type Task struct {
  12. Name string `yaml:"Name"`
  13. PM int `yaml:"PM"`
  14. TC int `yaml:"TC"`
  15. STC int `yaml:"STC"`
  16. Optional bool `yaml:"Optional"`
  17. }
  18. func main() {
  19. yamlData := []byte(`
  20. CategoryName:
  21. - Task1:
  22. Name: "Meeting"
  23. PM: 1
  24. TC: 0
  25. STC: 1
  26. Optional: false
  27. - Task2:
  28. Name: "Meeting v2"
  29. PM: 2
  30. TC: 0
  31. STC: 2
  32. Optional: false
  33. `)
  34. var config Config
  35. err := yaml.Unmarshal(yamlData, &config)
  36. if err != nil {
  37. log.Fatalf("Erreur lors de la décomposition du YAML : %v", err)
  38. }
  39. fmt.Printf("Configuration : %+v\n", config)
  40. }

以上是要翻译的代码部分。

英文:
  1. package main
  2. import (
  3. "fmt"
  4. "gopkg.in/yaml.v2"
  5. "io/ioutil"
  6. "log"
  7. )
  8. type Config struct {
  9. CategoryName []map[string]Task `yaml:"CategoryName"`
  10. }
  11. type Task struct {
  12. Name string `yaml:"Name"`
  13. PM int `yaml:"PM"`
  14. TC int `yaml:"TC"`
  15. STC int `yaml:"STC"`
  16. Optional bool `yaml:"Optional"`
  17. }
  18. func main() {
  19. yamlData := []byte(`
  20. CategoryName:
  21. - Task1:
  22. Name: "Meeting"
  23. PM: 1
  24. TC: 0
  25. STC: 1
  26. Optional: false
  27. - Task2:
  28. Name: "Meeting v2"
  29. PM: 2
  30. TC: 0
  31. STC: 2
  32. Optional: false
  33. `)
  34. var config Config
  35. err := yaml.Unmarshal(yamlData, &config)
  36. if err != nil {
  37. log.Fatalf("Erreur lors de la décomposition du YAML : %v", err)
  38. }
  39. fmt.Printf("Configuration : %+v\n", config)
  40. }

huangapple
  • 本文由 发表于 2022年7月26日 20:51:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/73123698.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定