Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Reading an array from a yaml file in GoLang

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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…

>Solution :

You have defined the outermost container as a map with a document key containing an array of Documents:

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}]
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading