diff --git a/.changelog/461d165a25e346669f076407175b6bd5.json b/.changelog/461d165a25e346669f076407175b6bd5.json new file mode 100644 index 000000000..3722d21a6 --- /dev/null +++ b/.changelog/461d165a25e346669f076407175b6bd5.json @@ -0,0 +1,8 @@ +{ + "id": "461d165a-25e3-4666-9f07-6407175b6bd5", + "type": "bugfix", + "description": "Fixes a bug where JSON object keys were not escaped.", + "modules": [ + "." + ] +} \ No newline at end of file diff --git a/encoding/json/escape_test.go b/encoding/json/escape_test.go new file mode 100644 index 000000000..c3a07a126 --- /dev/null +++ b/encoding/json/escape_test.go @@ -0,0 +1,49 @@ +package json + +import ( + "bytes" + "testing" +) + +func TestEscapeStringBytes(t *testing.T) { + cases := map[string]struct { + expected string + input []byte + }{ + "safeSet only": { + expected: `"mountainPotato"`, + input: []byte("mountainPotato"), + }, + "parenthesis": { + expected: `"foo\""`, + input: []byte(`foo"`), + }, + "double escape": { + expected: `"hello\\\\world"`, + input: []byte(`hello\\world`), + }, + "new line": { + expected: `"foo\nbar"`, + input: []byte("foo\nbar"), + }, + "carriage return": { + expected: `"foo\rbar"`, + input: []byte("foo\rbar"), + }, + "tab": { + expected: `"foo\tbar"`, + input: []byte("foo\tbar"), + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + var buffer bytes.Buffer + escapeStringBytes(&buffer, c.input) + expected := c.expected + actual := buffer.String() + if expected != actual { + t.Errorf("\nexpected %v \nactual %v", expected, actual) + } + }) + } +} diff --git a/encoding/json/object.go b/encoding/json/object.go index 15fb6478c..722346d03 100644 --- a/encoding/json/object.go +++ b/encoding/json/object.go @@ -17,9 +17,7 @@ func newObject(w *bytes.Buffer, scratch *[]byte) *Object { } func (o *Object) writeKey(key string) { - o.w.WriteRune(quote) - o.w.Write([]byte(key)) - o.w.WriteRune(quote) + escapeStringBytes(o.w, []byte(key)) o.w.WriteRune(colon) } diff --git a/encoding/json/object_test.go b/encoding/json/object_test.go index 5f09fb1ae..1e0830e05 100644 --- a/encoding/json/object_test.go +++ b/encoding/json/object_test.go @@ -7,9 +7,9 @@ import ( func TestObject(t *testing.T) { buffer := bytes.NewBuffer(nil) - scatch := make([]byte, 64) + scratch := make([]byte, 64) - object := newObject(buffer, &scatch) + object := newObject(buffer, &scratch) object.Key("foo").String("bar") object.Key("faz").String("baz") object.Close() @@ -19,3 +19,16 @@ func TestObject(t *testing.T) { t.Errorf("expected %+q, but got %+q", e, a) } } + +func TestObjectKey_escaped(t *testing.T) { + jsonEncoder := NewEncoder() + object := jsonEncoder.Object() + object.Key("foo\"").String("bar") + object.Key("faz").String("baz") + object.Close() + + e := []byte(`{"foo\"":"bar","faz":"baz"}`) + if a := object.w.Bytes(); bytes.Compare(e, a) != 0 { + t.Errorf("expected %+q, but got %+q", e, a) + } +}