jsoniter_string_test.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package jsoniter
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/json-iterator/go/require"
  7. "testing"
  8. "unicode/utf8"
  9. )
  10. func Test_read_normal_string(t *testing.T) {
  11. cases := map[string]string{
  12. `"0123456789012345678901234567890123456789"`: `0123456789012345678901234567890123456789`,
  13. `""`: ``,
  14. `"hello"`: `hello`,
  15. }
  16. for input, output := range cases {
  17. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  18. should := require.New(t)
  19. iter := ParseString(ConfigDefault, input)
  20. should.Equal(output, iter.ReadString())
  21. })
  22. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  23. should := require.New(t)
  24. iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
  25. should.Equal(output, iter.ReadString())
  26. })
  27. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  28. should := require.New(t)
  29. iter := ParseString(ConfigDefault, input)
  30. should.Equal(output, string(iter.ReadStringAsSlice()))
  31. })
  32. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  33. should := require.New(t)
  34. iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
  35. should.Equal(output, string(iter.ReadStringAsSlice()))
  36. })
  37. }
  38. }
  39. func Test_read_exotic_string(t *testing.T) {
  40. cases := map[string]string{
  41. `"hel\"lo"`: `hel"lo`,
  42. `"hel\nlo"`: "hel\nlo",
  43. `"\u4e2d\u6587"`: "中文",
  44. `"\ud83d\udc4a"`: "\xf0\x9f\x91\x8a", // surrogate
  45. }
  46. for input, output := range cases {
  47. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  48. should := require.New(t)
  49. iter := ParseString(ConfigDefault, input)
  50. should.Equal(output, iter.ReadString())
  51. })
  52. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  53. should := require.New(t)
  54. iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
  55. should.Equal(output, iter.ReadString())
  56. })
  57. }
  58. }
  59. func Test_read_string_as_interface(t *testing.T) {
  60. should := require.New(t)
  61. iter := ParseString(ConfigDefault, `"hello"`)
  62. should.Equal("hello", iter.Read())
  63. }
  64. func Test_write_string(t *testing.T) {
  65. should := require.New(t)
  66. str, err := MarshalToString("hello")
  67. should.Equal(`"hello"`, str)
  68. should.Nil(err)
  69. str, err = MarshalToString(`hel"lo`)
  70. should.Equal(`"hel\"lo"`, str)
  71. should.Nil(err)
  72. }
  73. func Test_write_val_string(t *testing.T) {
  74. should := require.New(t)
  75. buf := &bytes.Buffer{}
  76. stream := NewStream(ConfigDefault, buf, 4096)
  77. stream.WriteVal("hello")
  78. stream.Flush()
  79. should.Nil(stream.Error)
  80. should.Equal(`"hello"`, buf.String())
  81. }
  82. func Test_decode_slash(t *testing.T) {
  83. should := require.New(t)
  84. var obj interface{}
  85. should.NotNil(json.Unmarshal([]byte("\\"), &obj))
  86. should.NotNil(UnmarshalFromString("\\", &obj))
  87. }
  88. func Test_html_escape(t *testing.T) {
  89. should := require.New(t)
  90. output, err := json.Marshal(`>`)
  91. should.Nil(err)
  92. should.Equal(`"\u003e"`, string(output))
  93. output, err = ConfigCompatibleWithStandardLibrary.Marshal(`>`)
  94. should.Nil(err)
  95. should.Equal(`"\u003e"`, string(output))
  96. type MyString string
  97. output, err = ConfigCompatibleWithStandardLibrary.Marshal(MyString(`>`))
  98. should.Nil(err)
  99. should.Equal(`"\u003e"`, string(output))
  100. }
  101. func Test_string_encode_with_std(t *testing.T) {
  102. should := require.New(t)
  103. for i := 0; i < utf8.RuneSelf; i++ {
  104. input := string([]byte{byte(i)})
  105. stdOutputBytes, err := json.Marshal(input)
  106. should.Nil(err)
  107. stdOutput := string(stdOutputBytes)
  108. jsoniterOutputBytes, err := ConfigCompatibleWithStandardLibrary.Marshal(input)
  109. should.Nil(err)
  110. jsoniterOutput := string(jsoniterOutputBytes)
  111. should.Equal(stdOutput, jsoniterOutput)
  112. }
  113. }
  114. func Test_string_encode_with_std_without_html_escape(t *testing.T) {
  115. api := Config{EscapeHtml: false}.Froze()
  116. should := require.New(t)
  117. for i := 0; i < utf8.RuneSelf; i++ {
  118. input := string([]byte{byte(i)})
  119. buf := &bytes.Buffer{}
  120. encoder := json.NewEncoder(buf)
  121. encoder.SetEscapeHTML(false)
  122. err := encoder.Encode(input)
  123. should.Nil(err)
  124. stdOutput := buf.String()
  125. stdOutput = stdOutput[:len(stdOutput)-1]
  126. jsoniterOutputBytes, err := api.Marshal(input)
  127. should.Nil(err)
  128. jsoniterOutput := string(jsoniterOutputBytes)
  129. should.Equal(stdOutput, jsoniterOutput)
  130. }
  131. }
  132. func Test_unicode(t *testing.T) {
  133. should := require.New(t)
  134. output, _ := MarshalToString(map[string]interface{}{"a": "数字山谷"})
  135. should.Equal(`{"a":"数字山谷"}`, output)
  136. output, _ = Config{EscapeHtml: false}.Froze().MarshalToString(map[string]interface{}{"a": "数字山谷"})
  137. should.Equal(`{"a":"数字山谷"}`, output)
  138. }
  139. func Test_unicode_and_escape(t *testing.T) {
  140. should := require.New(t)
  141. output, err := MarshalToString(`"数字山谷"`)
  142. should.Nil(err)
  143. should.Equal(`"\"数字山谷\""`, output)
  144. output, err = ConfigFastest.MarshalToString(`"数字山谷"`)
  145. should.Nil(err)
  146. should.Equal(`"\"数字山谷\""`, output)
  147. }
  148. func Test_unsafe_unicode(t *testing.T) {
  149. ConfigDefault.cleanEncoders()
  150. should := require.New(t)
  151. output, err := ConfigDefault.MarshalToString("he\u2029\u2028he")
  152. should.Nil(err)
  153. should.Equal(`"he\u2029\u2028he"`, output)
  154. output, err = ConfigFastest.MarshalToString("he\u2029\u2028he")
  155. should.Nil(err)
  156. should.Equal("\"he\u2029\u2028he\"", output)
  157. }
  158. func Benchmark_jsoniter_unicode(b *testing.B) {
  159. for n := 0; n < b.N; n++ {
  160. iter := ParseString(ConfigDefault, `"\ud83d\udc4a"`)
  161. iter.ReadString()
  162. }
  163. }
  164. func Benchmark_jsoniter_ascii(b *testing.B) {
  165. iter := NewIterator(ConfigDefault)
  166. input := []byte(`"hello, world! hello, world!"`)
  167. b.ResetTimer()
  168. for n := 0; n < b.N; n++ {
  169. iter.ResetBytes(input)
  170. iter.ReadString()
  171. }
  172. }
  173. func Benchmark_jsoniter_string_as_bytes(b *testing.B) {
  174. iter := ParseString(ConfigDefault, `"hello, world!"`)
  175. b.ResetTimer()
  176. for n := 0; n < b.N; n++ {
  177. iter.ResetBytes(iter.buf)
  178. iter.ReadStringAsSlice()
  179. }
  180. }
  181. func Benchmark_json_unicode(b *testing.B) {
  182. for n := 0; n < b.N; n++ {
  183. result := ""
  184. json.Unmarshal([]byte(`"\ud83d\udc4a"`), &result)
  185. }
  186. }
  187. func Benchmark_json_ascii(b *testing.B) {
  188. for n := 0; n < b.N; n++ {
  189. result := ""
  190. json.Unmarshal([]byte(`"hello"`), &result)
  191. }
  192. }