diff --git a/test/integration/typeconv_funcs.bats b/test/integration/typeconv_funcs.bats index dbb83c15c..add034697 100644 --- a/test/integration/typeconv_funcs.bats +++ b/test/integration/typeconv_funcs.bats @@ -18,16 +18,30 @@ function teardown () { [[ "${output}" == "true" ]] } -@test "toJSONPretty" { - gomplate -i '{{ `{"hello": "world"}` | json | toJSONPretty " " }} -{{ toJSONPretty "" (`{"hello": "world"}` | json) }}' +@test "'toJSON' can handle nested maps" { + gomplate -i '{{ "foo:\n bar:\n baz: qux" | yaml | toJSON }}' [ "$status" -eq 0 ] - [[ "${output}" == "{ - \"hello\": \"world\" + [[ "${output}" == '{"foo":{"bar":{"baz":"qux"}}}' ]] +} + +@test "'toJSONPretty' can handle nested maps" { + gomplate -i '{{ `{"foo":{"bar":{"baz":"qux"}}}` | json | toJSONPretty " " }} +{{ toJSONPretty "" (`{"foo":{"bar":{"baz":"qux"}}}` | json) }}' + [ "$status" -eq 0 ] + [[ "${output}" == '{ + "foo": { + "bar": { + "baz": "qux" + } + } } { -\"hello\": \"world\" -}" ]] +"foo": { +"bar": { +"baz": "qux" +} +} +}' ]] } @test "indent" { diff --git a/typeconv.go b/typeconv.go index 76739b3f3..71cf34a82 100644 --- a/typeconv.go +++ b/typeconv.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "encoding/json" "fmt" "log" @@ -9,6 +10,8 @@ import ( "strings" yaml "gopkg.in/yaml.v2" + + "github.com/ugorji/go/codec" ) // TypeConv - type conversion function @@ -74,19 +77,26 @@ func marshalObj(obj interface{}, f func(interface{}) ([]byte, error)) string { return string(b) } +func toJSONBytes(in interface{}) []byte { + h := &codec.JsonHandle{} + h.Canonical = true + buf := new(bytes.Buffer) + codec.NewEncoder(buf, h).Encode(in) + return buf.Bytes() +} + // ToJSON - Stringify a struct as JSON func (t *TypeConv) ToJSON(in interface{}) string { - return marshalObj(in, json.Marshal) + return string(toJSONBytes(in)) } // ToJSONPretty - Stringify a struct as JSON (indented) func (t *TypeConv) toJSONPretty(indent string, in interface{}) string { - b, err := json.MarshalIndent(in, "", indent) - if err != nil { - log.Fatalf("Unable to marshal object %s: %v", in, err) - } + out := new(bytes.Buffer) + b := toJSONBytes(in) + json.Indent(out, b, "", indent) - return string(b) + return string(out.Bytes()) } // ToYAML - Stringify a struct as YAML diff --git a/typeconv_test.go b/typeconv_test.go index 85620b7cd..47907ce46 100644 --- a/typeconv_test.go +++ b/typeconv_test.go @@ -68,9 +68,9 @@ func TestToJSON(t *testing.T) { "foo": "bar", "one": 1, "true": true, - "down": map[string]interface{}{ - "the": map[string]interface{}{ - "rabbit": map[string]interface{}{ + "down": map[interface{}]interface{}{ + "the": map[interface{}]interface{}{ + "rabbit": map[interface{}]interface{}{ "hole": true, }, },