From 7b6434d5784b811d4a3e5b663cfacd2716bd7db9 Mon Sep 17 00:00:00 2001 From: Dave Henderson Date: Mon, 6 Mar 2017 16:41:28 -0500 Subject: [PATCH] Adding toJSON and toYAML functions Signed-off-by: Dave Henderson --- README.md | 43 ++++++++++++++++++++++++++++++++++++++++++- main.go | 2 ++ typeconv.go | 19 +++++++++++++++++++ typeconv_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index de7645885..6969686b5 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,10 @@ Gomplate is an alternative that will let you process templates which also includ - [Example](#example) - [`yamlArray`](#yamlarray) - [Example](#example) + - [`toJSON`](#tojson) + - [Example](#example) + - [`toYAML`](#toyaml) + - [Example](#example) - [`datasource`](#datasource) - [Examples](#examples) - [Basic usage](#basic-usage) @@ -111,7 +115,7 @@ $ apk add gomplate ... ``` -_Note: the Alpine version of gomplate may lag behind the latest release of gomplate._ +_Note: the Alpine version of gomplate may lag behind the latest release of gomplate._ ### use with Docker @@ -453,6 +457,43 @@ $ gomplate < input.tmpl Hello world ``` +#### `toJSON` + +Converts an object to a JSON document. Input objects may be the result of `json`, `yaml`, `jsonArray`, or `yamlArray` functions, or they could be provided by a `datasource`. + +##### Example + +_This is obviously contrived - `json` is used to create an object._ + +_`input.tmpl`:_ +``` +{{ (`{"foo":{"hello":"world"}}` | json).foo | toJSON }} +``` + +```console +$ gomplate < input.tmpl +{"hello":"world"} +``` + +#### `toYAML` + +Converts an object to a YAML document. Input objects may be the result of `json`, `yaml`, `jsonArray`, or `yamlArray` functions, or they could be provided by a `datasource`. + +##### Example + +_This is obviously contrived - `json` is used to create an object._ + +_`input.tmpl`:_ +``` +{{ (`{"foo":{"hello":"world"}}` | json).foo | toYAML }} +``` + +```console +$ gomplate < input.tmpl +hello: world + +``` + #### `datasource` Parses a given datasource (provided by the [`--datasource/-d`](#--datasource-d) argument). diff --git a/main.go b/main.go index cee8a3954..8f801d7f5 100644 --- a/main.go +++ b/main.go @@ -56,6 +56,8 @@ func NewGomplate(data *Data) *Gomplate { "yamlArray": typeconv.YAMLArray, "slice": typeconv.Slice, "join": typeconv.Join, + "toJSON": typeconv.ToJSON, + "toYAML": typeconv.ToYAML, "ec2meta": ec2meta.Meta, "ec2dynamic": ec2meta.Dynamic, "ec2tag": ec2info.Tag, diff --git a/typeconv.go b/typeconv.go index 86c8e7f24..27bb5e96e 100644 --- a/typeconv.go +++ b/typeconv.go @@ -64,6 +64,25 @@ func (t *TypeConv) YAMLArray(in string) []interface{} { return unmarshalArray(obj, in, yaml.Unmarshal) } +func marshalObj(obj interface{}, f func(interface{}) ([]byte, error)) string { + b, err := f(obj) + if err != nil { + log.Fatalf("Unable to marshal object %s: %v", obj, err) + } + + return string(b) +} + +// ToJSON - Stringify a struct as JSON +func (t *TypeConv) ToJSON(in interface{}) string { + return marshalObj(in, json.Marshal) +} + +// ToYAML - Stringify a struct as YAML +func (t *TypeConv) ToYAML(in interface{}) string { + return marshalObj(in, yaml.Marshal) +} + // Slice creates a slice from a bunch of arguments func (t *TypeConv) Slice(args ...interface{}) []interface{} { return args diff --git a/typeconv_test.go b/typeconv_test.go index d5f5637d2..dafcb8669 100644 --- a/typeconv_test.go +++ b/typeconv_test.go @@ -2,6 +2,7 @@ package main import ( "testing" + "time" "github.com/stretchr/testify/assert" ) @@ -59,6 +60,51 @@ func TestUnmarshalArray(t *testing.T) { `)) } +func TestToJSON(t *testing.T) { + ty := new(TypeConv) + expected := `{"down":{"the":{"rabbit":{"hole":true}}},"foo":"bar","one":1,"true":true}` + in := map[string]interface{}{ + "foo": "bar", + "one": 1, + "true": true, + "down": map[string]interface{}{ + "the": map[string]interface{}{ + "rabbit": map[string]interface{}{ + "hole": true, + }, + }, + }, + } + assert.Equal(t, expected, ty.ToJSON(in)) +} + +func TestToYAML(t *testing.T) { + ty := new(TypeConv) + expected := `d: 2006-01-02T15:04:05.999999999-07:00 +foo: bar +? |- + multi + line + key +: hello: world +one: 1 +"true": true +` + mst, _ := time.LoadLocation("MST") + in := map[string]interface{}{ + "foo": "bar", + "one": 1, + "true": true, + `multi +line +key`: map[string]interface{}{ + "hello": "world", + }, + "d": time.Date(2006, time.January, 2, 15, 4, 5, 999999999, mst), + } + assert.Equal(t, expected, ty.ToYAML(in)) +} + func TestSlice(t *testing.T) { ty := new(TypeConv) expected := []string{"foo", "bar"}