Home > database >  How to access 'map[string]interface {}' data from my yaml file
How to access 'map[string]interface {}' data from my yaml file

Time:11-11

I have a yaml file i am trying to read in and loop over to extract some of the data.

example of my yaml

---
THE/NAME/DOESNT/MATTER:
  TEST_NAME: THIS/IS/WHAT/IS/DISPLAYS/ON/THE/HTML
  RUN_PATH: example/testfiles/release
  SOMETHING_ELSE: [1,2,3]
ANOTHER/PATH/LIKE/STRING:
  TEST_NAME: USED/FOR/THE/HTML
  RUN_PATH: example/testfiles/foo

my code

package main
import (
    "fmt"
    "os"
    "io/ioutil"

    "gopkg.in/yaml.v3"
)

func main() {
    reportYAML := os.Args[1]
    // userDictionary := os.Args[2]

    yfile, err := ioutil.ReadFile(reportYAML)
    if err != nil {
        fmt.Printf("ERROR: Unable to open yaml file : %s\n", err)
    }
    data := make(map[interface{}]interface{})
    error := yaml.Unmarshal([]byte(yfile), &data)
    if error != nil {
        fmt.Printf("ERROR: Unable to read yaml file : %s\n", err)
    }
    for _, value := range data {
        fmt.Printf("%T\n", value)
    }
    
}

the yaml will repeat with a similar pattern and i am trying to extract both TEST_NAME and RUN_PATH. Printf with %T gives me map[string]interface {} and %s map[RUN_PATH:example/testfiles/release SOMETHING_ELSE:[%!s(int=1) %!s(int=2) %!s(int=3)] TEST_NAME:THIS/IS/WHAT/IS/DISPLAYS/ON/THE/HTML]

I've been trying value["TESTNAME"], value.(string)["TESTNAME"], value["TESTNAME"].(string) and a few other variations but they all give me errors.

I know this is a simple problem but i have very little experience with GO and can't work it out from previous, similar stackoverflow posts

additional context: each yaml top-level-key will contain multiple key:value pairs but i am only interested in the TEST_NAME and RUN_PATH

CodePudding user response:

If you only care about a few specific keys, just create a data structure to expose those values:

package main

import (
    "fmt"
    "io/ioutil"
    "os"

    "gopkg.in/yaml.v3"
)

type (
    Entry struct {
        TestName string `yaml:"TEST_NAME"`
        RunPath  string `yaml:"RUN_PATH"`
    }
)

func main() {
    reportYAML := os.Args[1]
    // userDictionary := os.Args[2]

    yfile, err := ioutil.ReadFile(reportYAML)
    if err != nil {
        fmt.Printf("ERROR: Unable to open yaml file : %s\n", err)
    }
    data := make(map[string]Entry)
    error := yaml.Unmarshal([]byte(yfile), &data)
    if error != nil {
        fmt.Printf("ERROR: Unable to read yaml file : %s\n", err)
    }
    for _, value := range data {
        fmt.Printf("test_name: %s\n", value.TestName)
        fmt.Printf("run_path: %s\n", value.RunPath)
    }
}

Running the above code against your example data produces:

test_name: THIS/IS/WHAT/IS/DISPLAYS/ON/THE/HTML
run_path: example/testfiles/release
test_name: USED/FOR/THE/HTML
run_path: example/testfiles/foo
  • Related