From d767ab7bf5a44a1bf43deba2b718e4569751fd57 Mon Sep 17 00:00:00 2001 From: Weston McNamee Date: Sat, 13 Jun 2020 11:54:56 -0700 Subject: [PATCH] =?UTF-8?q?fix(stdlib):=20=F0=9F=90=9B=20=20manifestJsonEx?= =?UTF-8?q?=20was=20escaping=20HTML?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit minimal repo: https://play.golang.org/p/GQBNMe6k_nm https://stackoverflow.com/questions/28595664/how-to-stop-json-marshal-from-escaping-and\nminimal fix proof: https://play.golang.org/p/SJM3KLkYW- resolves #423 --- builtins.go | 20 ++++++++++++++++---- testdata/builtinManifestJsonEx.golden | 1 + testdata/builtinManifestJsonEx.jsonnet | 22 ++++++++++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 testdata/builtinManifestJsonEx.golden create mode 100644 testdata/builtinManifestJsonEx.jsonnet diff --git a/builtins.go b/builtins.go index 4357f72..4a9e72e 100644 --- a/builtins.go +++ b/builtins.go @@ -1163,6 +1163,18 @@ func builtinParseJSON(i *interpreter, trace traceElement, str value) (value, err return jsonToValue(i, trace, parsedJSON) } +func jsonEncode(v interface{}) (string, error) { + buf := new(bytes.Buffer) + enc := json.NewEncoder(buf) + enc.SetEscapeHTML(false) + err := enc.Encode(v) + if err != nil { + return "", err + } + + return strings.TrimRight(buf.String(), "\n"), nil +} + // We have a very similar logic here /interpreter.go@v0.16.0#L695 and here: /interpreter.go@v0.16.0#L627 // These should ideally be unified // For backwards compatibility reasons, we are manually marshalling to json so we can control formatting @@ -1188,11 +1200,11 @@ func builtinManifestJSONEx(i *interpreter, trace traceElement, obj, indent value case *valueNull: return "null", nil case valueString: - b, err := json.Marshal(v.getGoString()) + jStr, err := jsonEncode(v.getGoString()) if err != nil { return "", i.Error(fmt.Sprintf("failed to marshal valueString to JSON: %v", err.Error()), trace) } - return string(b), nil + return jStr, nil case *valueNumber: return strconv.FormatFloat(v.value, 'f', -1, 64), nil case *valueBoolean: @@ -1233,11 +1245,11 @@ func builtinManifestJSONEx(i *interpreter, trace traceElement, obj, indent value return "", err } - fieldNameMarshalled, err := json.Marshal(fieldName) + fieldNameMarshalled, err := jsonEncode(fieldName) if err != nil { return "", i.Error(fmt.Sprintf("failed to marshal object fieldname to JSON: %v", err.Error()), trace) } - + newPath := append(path, fieldName) mvs, err := aux(fieldValue, newPath, newIndent) if err != nil { diff --git a/testdata/builtinManifestJsonEx.golden b/testdata/builtinManifestJsonEx.golden new file mode 100644 index 0000000..731a2d3 --- /dev/null +++ b/testdata/builtinManifestJsonEx.golden @@ -0,0 +1 @@ +"{\n \"bam\": true,\n \"bar\": \"bar\",\n \"baz\": 1,\n \"bazel\": 1.42,\n \"bim\": false,\n \"blamo\": {\n \"cereal\": [\n \"<>& fizbuzz\"\n ],\n \"treats\": [\n {\n \"name\": \"chocolate\"\n }\n ]\n },\n \"boom\": -1,\n \"foo\": \"bar\"\n}" diff --git a/testdata/builtinManifestJsonEx.jsonnet b/testdata/builtinManifestJsonEx.jsonnet new file mode 100644 index 0000000..c63139b --- /dev/null +++ b/testdata/builtinManifestJsonEx.jsonnet @@ -0,0 +1,22 @@ +local a = { + foo: "bar", + bar: self.foo, + baz: 1, + bazel: 1.42, + boom: -1, + bim: false, + bam: true, + blamo: { + cereal: [ + "<>& fizbuzz", + ], + + treats: [ + { + name: "chocolate", + } + ], + } +}; + +std.manifestJsonEx(a, " ") \ No newline at end of file