func (c *Config) marshal(i interface{}) ([]byte, error) {
	if c.OutYaml {
		return yaml.Marshal(i)
	}
	if c.Minimize {
		return json.Marshal(i)
	}
	return json.MarshalIndent(i, "", strings.Repeat(" ", c.Indent))
}
marshal marshals data in either yaml or json
package cfpgen
import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"sort"
	"strconv"
	"strings"
	"reflect"
	"bytes"
	"io"
	"gopkg.in/yaml.v2"
)
var (
	ErrMissingInFile     = errors.New("Missing required argument -f")
	ErrMissingParameters = errors.New("Parameters not found in file")
)
type Config struct {
	InFile                       string
	OutFile                      string
	Minimize                     bool
	Indent                       int
	Overwrite                    bool
	RemoveOldParamsNotInTemplate bool
	OutYaml                      bool
	InYaml                       bool
	Verbose                      bool
}
func Generate(c *Config, reader io.Reader) error {
	flag.Parse()
	var data []byte
	var err error
	if reader != nil {
		data, err = ioutil.ReadAll(reader)
		if err != nil {
			return err
		}
	}
	if c.InFile == "" && reader == nil {
		return ErrMissingInFile
	}
	m := make(map[string]interface{})
	if data == nil {
		data, err = ioutil.ReadFile(c.InFile)
		if err != nil {
			return err
		}
	}
	err = c.unmarshal(data, &m)
	if err != nil {
		return err
	}
	if _, ok := m["Parameters"]; !ok {
		return ErrMissingParameters
	}
	params := make(map[string]interface{})
	if c.InYaml {
		RecurseMapInterface(m["Parameters"].(map[interface{}]interface{}), params)
	} else {
		params = m["Parameters"].(map[string]interface{})
	}
	pl, err := c.GetParamList(params)
	if err != nil {
		return err
	}
	sort.Sort(pl)
	return c.ProcessPL(pl)
}
func (c *Config) GetParamList(params map[string]interface{}) (ParamList, error) {
	pl := make(ParamList, 0)
	for k := range params {
		m := make(map[string]interface{})
		v := params[k]
		switch val := v.(type) {
		case map[interface{}]interface{}:
			RecurseMapInterface(val, m)
		case map[string]interface{}:
			m = val
		}
		p := Parameter{ParameterKey: k}
		for k, v := range m {
			switch k {
			case "Default":
				p.Default = v
			case "AllowedValues":
				v, ok := v.([]interface{})
				if ok {
					p.AllowedValues = v
				} else {
					return nil, errors.New("AllowedValues was not an []interface{}")
				}
			case "Description":
				if s, ok := v.(string); ok {
					p.Description = s
				} else {
					return nil, errors.New("Description was not a string")
				}
			case "Type":
				if s, ok := v.(string); ok {
					p.Type = s
				} else {
					return nil, errors.New("Type was not a string")
				}
			case "AllowedPattern":
				if s, ok := v.(string); ok {
					p.AllowedPattern = s
				} else {
					return nil, errors.New("AllowedPattern was not a string")
				}
			}
		}
		pl = append(pl, p)
	}
	for i := range pl {
		var s string
		s = fmt.Sprintf("Type: %s", pl[i].Type)
		if c.Verbose {
			if pl[i].Default != nil {
				s += fmt.Sprintf(", Default: %v", pl[i].Default)
			}
			if pl[i].AllowedValues != nil {
				s += fmt.Sprintf(", AllowedValues: %v", pl[i].AllowedValues)
			}
			if pl[i].AllowedPattern != "" {
				s += fmt.Sprintf(", AllowedPattern: %s", pl[i].AllowedPattern)
			}
			if pl[i].Description != "" {
				s += fmt.Sprintf(", Description: %s", pl[i].Description)
			}
		}
		pl[i].ParameterValue = s
	}
	return pl, nil
}
func (c *Config) ProcessPL(pl ParamList) error {
	data, err := c.marshal(pl)
	if err != nil {
		return err
	}
	if c.OutFile != "" {
		if !c.Overwrite {
			odata, err := ioutil.ReadFile(c.OutFile)
			if err == nil {
				if len(odata) > 0 {
					opl := make(ParamList, 0)
					err = c.unmarshal(odata, &opl)
					if err != nil {
						return err
					}
					for _, nv := range pl {
						found := false
						for i, ov := range opl {
							if nv.ParameterKey == ov.ParameterKey {
								found = true
							}
							if i == len(opl)-1 && !found {
								opl = append(opl, nv)
							}
						}
					}
					if c.RemoveOldParamsNotInTemplate {
					outer:
						for i := 0; i < len(opl); i++ {
							found := false
							for _, nv := range pl {
								if nv.ParameterKey == opl[i].ParameterKey {
									found = true
								}
							}
							if !found {
								fmt.Println("Removing value", opl[i])
								opl = append(opl[:i], opl[i+1:]...)
								i--
								continue outer
							}
						}
					}
					sort.Sort(opl)
					data, err = c.marshal(opl)
					if err != nil {
						return err
					}
				}
			}
		}
		data = unescapeBrackets(data)
		err := ioutil.WriteFile(c.OutFile, data, 0644)
		if err != nil {
			return err
		}
	} else {
		data = unescapeBrackets(data)
		fmt.Print(string(data))
	}
	return nil
}