英文:
Reading an array from a yaml file in GoLang
问题
我正在尝试读取一个包含对象数组的 YAML 文件。
package config
import (
"gopkg.in/yaml.v3"
"log"
"os"
"path/filepath"
"runtime"
)
type DocumentationInfo struct {
docs []Document `yaml:"document"`
}
type Document struct {
title string `yaml:"title"`
fileName string `yaml:"filename"`
}
func (c *DocumentationInfo) Init() map[string]Document {
_, b, _, _ := runtime.Caller(0)
basepath := filepath.Dir(b)
yamlFile, err := os.ReadFile(basepath + "/documentation.yaml")
if err != nil {
log.Printf("yamlFile.Get err #%v ", err)
}
err = yaml.Unmarshal(yamlFile, c.docs)
if err != nil {
log.Fatalf("Unmarshal: %v", err)
}
docInfo := make(map[string]Document)
for _, doc := range c.docs {
docInfo[doc.fileName] = doc
}
return docInfo
}
func NewDocumentConfig() *DocumentationInfo {
return &DocumentationInfo{}
}
YAML 文件内容如下:
DocumentationInfo:
document:
- {fileName: "foo.md", title: "I am an foo title"}
- {fileName: "test.md", title: "I am an test title"}
- {fileName: "bar.md", title: "I am an bar title"}
- {fileName: "nice.md", title: "I am an nice title"}
错误信息如下:
2023/06/27 13:44:44 Unmarshal: yaml: unmarshal errors:
line 1: cannot unmarshal !!map into []config.Document
我不确定问题是否出在 YAML 文件的语法上,因为它与 JSON 类似,但是根据文档交叉引用,它看起来是正确的。
如果有任何建议,将不胜感激...
英文:
I am trying to read a yaml file that has an array of objects
package config
import (
"gopkg.in/yaml.v3"
"log"
"os"
"path/filepath"
"runtime"
)
type DocumentationInfo struct {
docs []Document `yaml:"document"`
}
type Document struct {
title string `yaml:"title"`
fileName string `yaml:"filename"`
}
func (c *DocumentationInfo) Init() map[string]Document {
_, b, _, _ := runtime.Caller(0)
basepath := filepath.Dir(b)
yamlFile, err := os.ReadFile(basepath + "/documentation.yaml")
if err != nil {
log.Printf("yamlFile.Get err #%v ", err)
}
err = yaml.Unmarshal(yamlFile, c.docs)
if err != nil {
log.Fatalf("Unmarshal: %v", err)
}
docInfo := make(map[string]Document)
for _, doc := range c.docs {
docInfo[doc.fileName] = doc
}
return docInfo
}
func NewDocumentConfig() *DocumentationInfo {
return &DocumentationInfo{}
}
yaml file
DocumentationInfo:
document:
- {fileName: "foo.md", title: "I am an foo title"}
- {fileName: "test.md", title: "I am an test title"}
- {fileName: "bar.md", title: "I am an bar title"}
- {fileName: "nice.md", title: "I am an nice title"}
error
2023/06/27 13:44:44 Unmarshal: yaml: unmarshal errors:
line 1: cannot unmarshal !!map into []config.Document
I am not sure if the issue is the yaml file syntax because it is similar to json, however cross referencing documentation it looks correct.
Any advice would be appreciated...
答案1
得分: 0
你已经将最外层的容器定义为一个包含一个名为document
的数组的DocumentationInfo
映射:
type DocumentationInfo struct {
docs []Document `yaml:"document"`
}
但是这不是你的输入数据的结构,它看起来像这样:
DocumentationInfo:
document:
- {fileName: "foo.md", title: "I am an foo title"}
- {fileName: "test.md", title: "I am an test title"}
- {fileName: "bar.md", title: "I am an bar title"}
- {fileName: "nice.md", title: "I am an nice title"}
最外层的元素是一个包含DocumentationInfo
键的映射(而该键的值是包含document
键的映射)。你需要重新定义你的类型,像这样(我将其转换为package main
,以便我可以在本地进行测试):
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"gopkg.in/yaml.v3"
)
type DocumentationInfoFile struct {
DocumentationInfo DocumentationInfo `yaml:"DocumentationInfo"`
}
type DocumentationInfo struct {
Docs []Document `yaml:"document"`
}
type Document struct {
Title string `yaml:"title"`
FileName string `yaml:"fileName"`
}
func (docinfo *DocumentationInfoFile) Init() map[string]Document {
_, b, _, _ := runtime.Caller(0)
basepath := filepath.Dir(b)
yamlFile, err := os.ReadFile(basepath + "/documentation.yaml")
if err != nil {
log.Printf("yamlFile.Get err #%v ", err)
}
err = yaml.Unmarshal(yamlFile, docinfo)
if err != nil {
log.Fatalf("Unmarshal: %v", err)
}
docmap := make(map[string]Document)
for _, doc := range docinfo.DocumentationInfo.Docs {
docmap[doc.FileName] = doc
}
return docmap
}
func NewDocumentConfig() *DocumentationInfoFile {
return &DocumentationInfoFile{}
}
func main() {
d := NewDocumentConfig()
docmap := d.Init()
fmt.Printf("%+v\n", docmap)
}
运行上述代码会产生以下结果:
map[bar.md:{Title:I am an bar title FileName:bar.md} foo.md:{Title:I am an foo title FileName:foo.md} nice.md:{Title:I am an nice title FileName:nice.md} test.md:{Title:I am an test title FileName:test.md}]
英文:
You have defined the outermost container as a map with a document
key containing an array of Document
s:
type DocumentationInfo struct {
docs []Document `yaml:"document"`
}
But that is not the structure of your input data, which looks like this:
DocumentationInfo:
document:
- {fileName: "foo.md", title: "I am an foo title"}
- {fileName: "test.md", title: "I am an test title"}
- {fileName: "bar.md", title: "I am an bar title"}
- {fileName: "nice.md", title: "I am an nice title"}
The outer element is a map that contains a DocumentationInfo
key (and the value of that key is your map with the document
key). You would need to redefine your types like this (I've turned this into package main
so I can run it locally for testing):
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"gopkg.in/yaml.v3"
)
type DocumentationInfoFile struct {
DocumentationInfo DocumentationInfo `yaml:"DocumentationInfo"`
}
type DocumentationInfo struct {
Docs []Document `yaml:"document"`
}
type Document struct {
Title string `yaml:"title"`
FileName string `yaml:"fileName"`
}
func (docinfo *DocumentationInfoFile) Init() map[string]Document {
_, b, _, _ := runtime.Caller(0)
basepath := filepath.Dir(b)
yamlFile, err := os.ReadFile(basepath + "/documentation.yaml")
if err != nil {
log.Printf("yamlFile.Get err #%v ", err)
}
err = yaml.Unmarshal(yamlFile, docinfo)
if err != nil {
log.Fatalf("Unmarshal: %v", err)
}
docmap := make(map[string]Document)
for _, doc := range docinfo.DocumentationInfo.Docs {
docmap[doc.FileName] = doc
}
return docmap
}
func NewDocumentConfig() *DocumentationInfoFile {
return &DocumentationInfoFile{}
}
func main() {
d := NewDocumentConfig()
docmap := d.Init()
fmt.Printf("%+v\n", docmap)
}
Running the above code produces:
map[bar.md:{Title:I am an bar title FileName:bar.md} foo.md:{Title:I am an foo title FileName:foo.md} nice.md:{Title:I am an nice title FileName:nice.md} test.md:{Title:I am an test title FileName:test.md}]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论