gojay

high performance JSON encoder/decoder with stream API for Golang
git clone git://git.lair.cx/gojay
Log | Files | Refs | README | LICENSE

commit 4ddbe4cccf1017685edfbaf701f8248d743597e8
parent 8509e0d6dff41d388f3580537e58771bca26adb8
Author: francoispqt <francois@parquet.ninja>
Date:   Sat,  5 May 2018 00:35:08 +0800

add escaping sequence for encoding

Diffstat:
Mencode_builder.go | 24+++++++++++++++++++++++-
Mencode_string.go | 14+++++++-------
Mencode_string_test.go | 50++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 80 insertions(+), 8 deletions(-)

diff --git a/encode_builder.go b/encode_builder.go @@ -1,7 +1,6 @@ // Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. - package gojay // grow grows b's capacity, if necessary, to guarantee space for @@ -35,3 +34,26 @@ func (enc *Encoder) writeByte(c byte) { func (enc *Encoder) writeString(s string) { enc.buf = append(enc.buf, s...) } + +func (enc *Encoder) writeStringEscape(s string) { + l := len(s) + for i := 0; i < l; i++ { + switch s[i] { + case '\\', '"': + enc.writeByte('\\') + enc.writeByte(s[i]) + case '\n': + enc.writeByte('\\') + enc.writeByte('n') + case '\r': + enc.writeByte('\\') + enc.writeByte('r') + case '\t': + enc.writeByte('\\') + enc.writeByte('t') + default: + enc.writeByte(s[i]) + } + } + +} diff --git a/encode_string.go b/encode_string.go @@ -17,7 +17,7 @@ func (enc *Encoder) EncodeString(s string) error { // encodeString encodes a string to func (enc *Encoder) encodeString(v string) ([]byte, error) { enc.writeByte('"') - enc.writeString(v) + enc.writeStringEscape(v) enc.writeByte('"') return enc.buf, nil } @@ -29,7 +29,7 @@ func (enc *Encoder) AddString(v string) { enc.writeByte(',') } enc.writeByte('"') - enc.writeString(v) + enc.writeStringEscape(v) enc.writeByte('"') } @@ -44,7 +44,7 @@ func (enc *Encoder) AddStringOmitEmpty(v string) { enc.writeByte(',') } enc.writeByte('"') - enc.writeString(v) + enc.writeStringEscape(v) enc.writeByte('"') } @@ -55,9 +55,9 @@ func (enc *Encoder) AddStringKey(key, v string) { enc.writeByte(',') } enc.writeByte('"') - enc.writeString(key) + enc.writeStringEscape(key) enc.writeBytes(objKeyStr) - enc.writeString(v) + enc.writeStringEscape(v) enc.writeByte('"') } @@ -72,8 +72,8 @@ func (enc *Encoder) AddStringKeyOmitEmpty(key, v string) { enc.writeByte(',') } enc.writeByte('"') - enc.writeString(key) + enc.writeStringEscape(key) enc.writeBytes(objKeyStr) - enc.writeString(v) + enc.writeStringEscape(v) enc.writeByte('"') } diff --git a/encode_string_test.go b/encode_string_test.go @@ -30,6 +30,56 @@ func TestEncoderStringEncodeAPI(t *testing.T) { builder.String(), "Result of marshalling is different as the one expected") }) + t.Run("utf8-multibyte", func(t *testing.T) { + str := "テュールスト マーティン ヤコブ 😁" + builder := &strings.Builder{} + enc := NewEncoder(builder) + err := enc.EncodeString(str) + assert.Nil(t, err, "Error should be nil") + assert.Equal( + t, + `"テュールスト マーティン ヤコブ 😁"`, + builder.String(), + "Result of marshalling is different as the one expected") + }) + t.Run("escaped-sequence1", func(t *testing.T) { + str := `テュールスト マ\ーテ +ィン ヤコブ 😁` + builder := &strings.Builder{} + enc := NewEncoder(builder) + err := enc.EncodeString(str) + assert.Nil(t, err, "Error should be nil") + assert.Equal( + t, + `"テュールスト マ\\ーテ\nィン ヤコブ 😁"`, + builder.String(), + "Result of marshalling is different as the one expected") + }) + t.Run("escaped-sequence2", func(t *testing.T) { + str := `テュールスト マ\ーテ +ィン ヤコブ 😁 ` + builder := &strings.Builder{} + enc := NewEncoder(builder) + err := enc.EncodeString(str) + assert.Nil(t, err, "Error should be nil") + assert.Equal( + t, + `"テュールスト マ\\ーテ\nィン ヤコブ 😁\t"`, + builder.String(), + "Result of marshalling is different as the one expected") + }) + t.Run("escaped-sequence3", func(t *testing.T) { + str := "hello \r world" + builder := &strings.Builder{} + enc := NewEncoder(builder) + err := enc.EncodeString(str) + assert.Nil(t, err, "Error should be nil") + assert.Equal( + t, + `"hello \r world"`, + builder.String(), + "Result of marshalling is different as the one expected") + }) } func TestEncoderStringEncodeAPIErrors(t *testing.T) {