Skip to content

Commit

Permalink
yaml2go: convert yamls to go structs
Browse files Browse the repository at this point in the history
  • Loading branch information
PrasadG193 committed Jul 19, 2019
1 parent 02e930b commit 88dfb5d
Showing 1 changed file with 120 additions and 0 deletions.
120 changes: 120 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package main

import (
"bufio"
"fmt"
"go/format"
"gopkg.in/yaml.v2"
// "io/ioutil"
"log"
"os"
"reflect"
"strings"
)

type Yaml2Go struct {
Result string
}

func (yg *Yaml2Go) AppendResult(line string) {
yg.Result += line
}

func main() {
// Read input from the console
var data string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
data += scanner.Text() + "\n"
}
if err := scanner.Err(); err != nil {
log.Fatal("Error while reading input:", err)
}

// Unmarshal to map[string]interface{}
var t map[string]interface{}
err := yaml.Unmarshal([]byte(data), &t)
if err != nil {
log.Fatal("Failed to parse input")
}

y2g := Yaml2Go{}
y2g.AppendResult("type Yaml2Go struct {\n")
y2g.Convert(t)
y2g.AppendResult("}")

// Convert result into go format
goFormat, err := format.Source([]byte(y2g.Result))
if err != nil {
log.Fatal("go fmt error:", err)
}
fmt.Printf(string(goFormat))
return
}

// removeUnderscores and camelize string
func goKeyFormat(key string) string {
var st string
strList := strings.Split(key, "_")
for _, str := range(strList) {
st += strings.Title(str)
}
if len(st) == 0 {
st = key
}
return st
}

// Convert transforms map[string]interfaceP{} to go struct
func (yg *Yaml2Go) Convert(obj map[string]interface{}) {
for k, v := range obj {
yg.Structify(k, v, false)
}
}

// Structify transforms map key values to struct fields
func (yg *Yaml2Go) Structify(k string, v interface{}, arrayElem bool) {
if reflect.TypeOf(v) == nil {
yg.AppendResult(fmt.Sprintf("%s interface{} `yaml:\"%s\"`\n", goKeyFormat(k), k))
return
}

switch reflect.TypeOf(v).Kind() {
case reflect.Map:
switch val := v.(type) {
case map[interface{}]interface{}:
if !arrayElem {
yg.AppendResult(fmt.Sprintf("%s struct { \n", goKeyFormat(k)))
}
for k1, v1 := range val {
if _, ok := k1.(string); ok {
yg.Structify(k1.(string), v1, false)
}
}
if !arrayElem {
yg.AppendResult(fmt.Sprintf("} `yaml:\"%s\"`\n", k))
}
}

case reflect.Slice:
val := v.([]interface{})
if len(val) != 0 {
return
}
switch val[0].(type) {

case string, int, bool:
yg.AppendResult(fmt.Sprintf("%s []%s `yaml:\"%s\"`\n", goKeyFormat(k), reflect.TypeOf(val[0]), k))

case map[interface{}]interface{}:
yg.AppendResult(fmt.Sprintf("%s []struct { \n", goKeyFormat(k)))
for _, v1 := range val {
yg.Structify(goKeyFormat(k), v1, true)
}
yg.AppendResult(fmt.Sprintf("} `yaml:\"%s\"`\n", k))
}

default:
yg.AppendResult(fmt.Sprintf("%s %s `yaml:\"%s\"`\n", goKeyFormat(k), reflect.TypeOf(v).String(), k))
}
}

0 comments on commit 88dfb5d

Please sign in to comment.