user6124024
user6124024

Reputation:

Parse yaml return empty object

I have the following yaml which I need to parse to struct. In the builds property I got empty value while debug, what am I missing here?

I use "gopkg.in/yaml.v2"

- name: srv
    type: java
    path: srv
    builds:
     - name: db
        properties:
           JBR_CONFIG_RESOURCE_CONFIG: '[META-INF/context.xml:
              {"service_name" : "~{h-container}"}]'
           TEST2: aaaa

The struct is

type Runs struct {
    Name       string
    Type       string
    Path       string     `yaml:"path,omitempty"`
    Builds   []Builds `yaml:”builds,omitempty"`
}

type Builds struct {
    Name       string     `yaml:"name,omitempty"`
    Properties Properties `yaml:"properties,omitempty"`
}

type Properties map[string]string

Upvotes: 1

Views: 7377

Answers (2)

ttomalak
ttomalak

Reputation: 2036

Properly formated yaml is the first thing that you should consider. If u wanna have one Runs you should have your yaml formated something like that

name: srv
builds:
  -
    name: db
    properties:
      JBR_CONFIG_RESOURCE_CONFIG: "[META-INF/context.xml:
      {\"service_name\" : \"~{h-container}\"}]"
      TEST2: aaaa
path: srv
type: java

But then i u wanna have more of this object you need to group them in one parameter. It can look like this

runs:
  -
    name: srv
    builds:
      -
        name: db
        properties:
          JBR_CONFIG_RESOURCE_CONFIG: "[META-INF/context.xml:
          {\"service_name\" : \"~{h-container}\"}]"
          TEST2: aaaa
    path: srv
    type: java
  -
    name: srv2
    builds:
      -
        name: db2
        properties:
          JBR_CONFIG_RESOURCE_CONFIG: "[META-INF/context.xml:
          {\"service_name\" : \"~{h-container}\"}]"
          TEST2: aaaa2
    path: srv2
    type: java2

And then in your code could look like this

package main

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

type Document struct {
    Runs []Runs `yaml:"runs,omitempty"`
}
type Runs struct {
    Name   string   `yaml:"name,omitempty"`
    Type   string   `yaml:"type,omitempty"`
    Path   string   `yaml:"path,omitempty"`
    Builds []Builds `yaml:"builds,omitempty"`
}

type Builds struct {
    Name       string            `yaml:"name,omitempty"`
    Properties map[string]string `yaml:"properties,omitempty"`
}

func main() {

    var document Document
    reader, err := os.Open("demo.yml")
    if err != nil {
        log.Fatal(err)
    }
    buf, _ := ioutil.ReadAll(reader)
    yaml.Unmarshal(buf, &document)
    if err := yaml.Unmarshal(buf, &document); err != nil {
        fmt.Print(err)
        os.Exit(1)
    }
    fmt.Println(document)
}

Upvotes: 1

elmiomar
elmiomar

Reputation: 2022

Make sure your yaml file is formatted correctly. Check with this tool.

The following piece of code worked fine.

package main

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

type Runs struct {
    Name   string
    Type   string
    Path   string   `yaml:"path,omitempty"`
    Builds []Builds `yaml:”builds,omitempty"`
}

type Builds struct {
    Name       string     `yaml:"name,omitempty"`
    Properties Properties `yaml:"properties,omitempty"`
}

type Properties map[string]string

func main() {
    data := `builds: 
  - 
    name: db
    properties: 
      JBR_CONFIG_RESOURCE_CONFIG: "[META-INF/context.xml: {\"service_name\" : \"~{h-container}\"}]"
      TEST2: aaaa
name: srv
path: srv
type: java
`

    runs := Runs{}

    err := yaml.Unmarshal([]byte(data), &runs)
    if err != nil {
        log.Fatalf("error: %v", err)
    }
    fmt.Printf("--- t:\n%v\n\n", runs)
    d, err := yaml.Marshal(&runs)
    if err != nil {
        log.Fatalf("error: %v", err)
    }
    fmt.Printf("--- t dump:\n%s\n\n", string(d))
}

I hope this helps!

Upvotes: 0

Related Questions