Home > Software design >  Unable to extract key/value pairs from a map obtained through YAML
Unable to extract key/value pairs from a map obtained through YAML

Time:01-06

I use the goldmark-meta package to read a YAML file. The contents I'm interested in look like this in the YAML:

burger:
- a: ay
- b: bee
- c: see

I want to get access to both keys and values of the returned interface, and I'm stuck. Iterating through the return gives me a list of the key/value pairs, but I don't know how to obtain any info when I don't know the key names in advance. This program prints out the following:

func (c *config) burger() string {
    // c.pageFm is type map[string]interface{}
    b, ok := c.pageFm["burger"].([]interface{})
    if !ok {
    // No burger entry  in yaml
        return ""
    }
  debug("Burger list has %v items:\n%v", len(b), b)  
  debug("Type: %v", reflect.TypeOf(b))
  for i := 0; i < len(b); i   {
    debug("%v", b[i])
  }
 return ""
}
Burger list has 3 items:
[map[a:ay] map[b:bee] map[c:see]]
Type: []interface {}
map[a:ay]
map[b:bee]
map[c:see]

How do I obtain the key and value strings?

CodePudding user response:

In your YAML data, you have a key (burger) the value of which is a list of maps (and each map has a single key). We can iterate over the items in burger like this:

b, ok := c.pageFm["burger"].([]interface{})
if !ok {
  return ""
}

for _, item := range burger {
  ...
}

For each item, we can iterate over available keys and values:

for _, item := range burger {
  for k, v := range item.(map[interface{}]interface{}) {
    ...
  }
}

We can convert keys and values from interface{} into string using fmt.Sprintf:

for _, item := range burger {
  for k, v := range item.(map[interface{}]interface{}) {
    k_str := fmt.Sprintf("%v", k)
    v_str := fmt.Sprintf("%v", v)

    fmt.Printf("key %s value %s\n", k_str, v_str)
  }
}

Starting with the sample code from goldmark-meta, I put together this example:

package main

import (
    "bytes"
    "fmt"

    "github.com/yuin/goldmark"
    meta "github.com/yuin/goldmark-meta"
    "github.com/yuin/goldmark/parser"
)

func main() {
    markdown := goldmark.New(
        goldmark.WithExtensions(
            meta.Meta,
        ),
    )
    source := `---
burger:
- a: ay
- b: bee
- c: see
---

# Hello goldmark-meta
`

    var buf bytes.Buffer
    context := parser.NewContext()
    if err := markdown.Convert([]byte(source), &buf, parser.WithContext(context)); err != nil {
        panic(err)
    }
    metaData := meta.Get(context)
    burger := metaData["burger"].([]interface{})
    for _, item := range burger {
        for k, v := range item.(map[interface{}]interface{}) {
            k_str := fmt.Sprintf("%v", k)
            v_str := fmt.Sprintf("%v", v)
            fmt.Printf("key %s value %s\n", k_str, v_str)
        }
    }
}

Which outputs:

key a value ay
key b value bee
key c value see
  •  Tags:  
  • go
  • Related