cannot unmarshal !!seq into string in Go

Viewed 6366

I am getting the following error while using sequence of array in yaml file. I am not sure what fix required to be applied as I am new to 'Go' and learning the program.

2021/07/28 14:16:07 yaml: unmarshal errors:
  line 3: cannot unmarshal !!seq into string

Yaml:

ENV: attributes: - foo - boo - coo

code:

package test

import (
    "fmt"
    "gopkg.in/yaml.v3"
    "io/ioutil"
    "log"
    "testing"
)

type ENV struct {
    Attributes string `yaml:"attributes"`
}


func TestTerraformAzureCosmosDBExample(t *testing.T) {


    yFile, err := ioutil.ReadFile("config.yaml")


    if err != nil {
        log.Fatal(err)
    }

    data := make(map[string]ENV)

    err = yaml.Unmarshal(yFile, &data)
    if err != nil {
        log.Fatal(err)
    }
    for k, v := range data {
        fmt.Printf(`key: %v, value: %v`, k,v)
    }

}

Expected:

foo boo coo

Actual:

C:\Pfoo\boo>go test -v
=== RUN   TestTerraformAzureCosmosDBExample
2021/07/28 14:16:07 yaml: unmarshal errors:
  line 3: cannot unmarshal !!seq into string
exit status 1
FAIL    foo_test   0.199s
3 Answers

As mkopriva, said in the comments, you should change to []string, so the struct would be

type ENV struct {
    Attributes []string `yaml:"attributes"`
}

And why is that ? the yaml, reconizes the ENV: attributes: - foo - boo - coo as a array. What you can do to turn into one string, is use: strings.Join(String Slice,{ something to separate, you can let this as "")`

the imports are : "strings", and strings.Join returns a string.

As per suggestion of mkopriva changing Attributes field to string[] instead of string:

package test

import (
    "fmt"
    "gopkg.in/yaml.v3"
    "io/ioutil"
    "log"
    "testing"
)

type ENV struct {
    Attributes []string `yaml:"attributes"`
}

func TestTerraformAzureCosmosDBExample(t *testing.T) {

    yFile, err := ioutil.ReadFile("config.yaml")

    if err != nil {
        log.Fatal(err)
    }

    data := make(map[string]ENV)

    err = yaml.Unmarshal(yFile, &data)
    if err != nil {
        log.Fatal(err)
    }
    for k, v := range data {
        fmt.Printf(`key: %v, value: %v`, k, v)
    }

}

Here is an example I did. Hope it helps

package main

import (
    "fmt"
    "gopkg.in/yaml.v2"
    "io/ioutil"
    "log"
)

type Image struct {
    Name  string `yaml:"name"`
    Image string `yaml:"image"`
}

type Specification struct {
    Spec struct {
        Container []Image `yaml:"containers,flow"`
    }
}

func main() {
    container := Specification{}

    content, err := ioutil.ReadFile("final-result.yml")
    if err != nil {
        log.Fatal(err.Error())
        return
    }

    err = yaml.Unmarshal(content, &container)
    if err != nil {
        log.Fatalf("error: %v", err)
    }
    log.Println(container)
    for _, ct := range container.Spec.Container {
        fmt.Println(ct.Name)
    }

}
spec:
  containers:
    - name: nginx
      image: nginx:1.14.2
    - name: php
      image: php:1.4.8
    - name: golang
      image: golang:1.4.3

Output

nginx
php
golang
Related