user6124024
user6124024

Reputation:

Parse yaml file to predefined struct in go

I’ve multiple yaml files which need to be parsed and have exactly the same structure

schema: "1.0.0"
id: test
version: "1.2.3"


dependency :
  - name: ui
    type: runner
    cwd: /ui
    install:
       - name: api
         group: test
         properties:
             name: app
             url: appUrl

  - name: backend
    type: mongoDb
    path: be
    install:
       - name: db
         type: mongo
    provides:
       - name: api
         properties:
            url: url

The schema section is mandatory for all the yaml which the app should get always

The dependency tag can contain 1..n entries with mandatory fields ,name, type, cwd

The dependency tag can (or not) contain install section with name and properties which is mandatory

The dependency tag can (or not) contain provides section with name and which is mandatory

The install can have properties and the provides also can have properties

I am using a yaml parser to parse the files but my question is how in Golang I can build struct that when I parse the doc it will automatically fill the main struct and will include the sub structs (such as dependency/ install sections )

I have tried something like

type main struct {
    schema struct {
        schema  string
        id int
        version string
    }

    dependency struct {
        name  string
        type string
        cwd string

    install struct {
        name  string
    }


}

In the install section, it can be group or type or both and it can have also properties section, so I'm not sure how to build some generic /extendable struct which I use to parse the document (the document have close list of properties, what I put in the example describe the most options)

I use this lib to parse the doc

yaml parser

enter image description here

Upvotes: 0

Views: 7934

Answers (1)

Vane Trajkov
Vane Trajkov

Reputation: 768

Your struct definition should be something like this

type Yaml struct {
    Schema     string
    ID         string
    Version    string
    Dependency []Dependency
}

type Dependency struct {
    Name     string
    Type     string
    CWD      string
    Install  []Install
    Provides []Provide
}

type Install struct {
    Name       string
    Group      string
    Type       string
    Properties Properties
}

type Properties struct {
    Name string
    URL  string
}

type Provide struct {
    Name       string
    Properties Properties
}

Here is full sample code:

package main

import (
    "fmt"
    "io/ioutil"
    "log"

    "gopkg.in/yaml.v2"
)

var data = `
schema: "1.0.0"
id: test
version: "1.2.3"


dependency :
  - name: ui
    type: runner
    cwd: /ui
    install:
       - name: api
         group: test
         properties:
             name: app
             url: appUrl

  - name: backend
    type: mongoDb
    path: be
    install:
       - name: db
         type: mongo
    provides:
       - name: api
         properties:
             url: url
`

type Yaml struct {
    Schema     string
    ID         string
    Version    string
    Dependency []Dependency
}

type Dependency struct {
    Name     string
    Type     string
    CWD      string
    Install  []Install
    Provides []Provide
}

type Install struct {
    Name       string
    Group      string
    Type       string
    Properties Properties
}

type Properties struct {
    Name string
    URL  string
}

type Provide struct {
    Name       string
    Properties Properties
}

func main() {
    y := Yaml{}

    err := yaml.Unmarshal([]byte(data), &y)
    if err != nil {
        log.Fatalf("error: %v", err)
    }
    fmt.Printf("%+v\n", y)

}

Output

{Schema:1.0.0 ID:test Version:1.2.3 Dependency:[{Name:ui Type:runner CWD:/ui Install:[{Name:api Group:test Type: Properties:{Name:appURL:appUrl}}] Provides:[]} {Name:backend Type:mongoDb CWD: Install:[{Name:db Group: Type:mongo Properties:{Name: URL:}}] Provides:[{Name:api Properties:{Name: URL:url}}]}]}

If you want to read from a yaml file, in the main func just replace:

err := yaml.Unmarshal([]byte(data), &y)

with

yamlFile, err := ioutil.ReadFile("yaml_sample.yaml")
if err != nil {
    log.Printf("yamlFile.Get err   #%v ", err)
}
err = yaml.Unmarshal(yamlFile, &y)

Upvotes: 4

Related Questions