1
2
3
4
5 package json_test
6
7 import (
8 "bytes"
9 "compress/gzip"
10 "fmt"
11 "io"
12 "io/ioutil"
13 "log"
14 "net"
15 "net/http"
16 "net/http/httptest"
17 "reflect"
18 "strconv"
19 "strings"
20 "testing"
21
22 "github.com/goccy/go-json"
23 )
24
25
26
27 var streamTest = []interface{}{
28 0.1,
29 "hello",
30 nil,
31 true,
32 false,
33 []interface{}{"a", "b", "c"},
34 map[string]interface{}{"K": "Kelvin", "ß": "long s"},
35 3.14,
36 }
37
38 var streamEncoded = `0.1
39 "hello"
40 null
41 true
42 false
43 ["a","b","c"]
44 {"ß":"long s","K":"Kelvin"}
45 3.14
46 `
47
48 func TestStreamEncoder(t *testing.T) {
49 for i := 0; i <= len(streamTest); i++ {
50 var buf bytes.Buffer
51 enc := json.NewEncoder(&buf)
52
53 enc.SetIndent(">", ".")
54 enc.SetIndent("", "")
55 for j, v := range streamTest[0:i] {
56 if err := enc.Encode(v); err != nil {
57 t.Fatalf("encode #%d: %v", j, err)
58 }
59 }
60 if have, want := buf.String(), nlines(streamEncoded, i); have != want {
61 t.Errorf("encoding %d items: mismatch", i)
62 diff(t, []byte(have), []byte(want))
63 break
64 }
65 }
66 }
67
68 var streamEncodedIndent = `0.1
69 "hello"
70 null
71 true
72 false
73 [
74 >."a",
75 >."b",
76 >."c"
77 >]
78 {
79 >."ß": "long s",
80 >."K": "Kelvin"
81 >}
82 3.14
83 `
84
85 func TestEncoderIndent(t *testing.T) {
86 var buf bytes.Buffer
87 enc := json.NewEncoder(&buf)
88 enc.SetIndent(">", ".")
89 for _, v := range streamTest {
90 enc.Encode(v)
91 }
92 if have, want := buf.String(), streamEncodedIndent; have != want {
93 t.Error("indented encoding mismatch")
94 diff(t, []byte(have), []byte(want))
95 }
96 }
97
98 type strMarshaler string
99
100 func (s strMarshaler) MarshalJSON() ([]byte, error) {
101 return []byte(s), nil
102 }
103
104 type strPtrMarshaler string
105
106 func (s *strPtrMarshaler) MarshalJSON() ([]byte, error) {
107 return []byte(*s), nil
108 }
109
110 func TestEncoderSetEscapeHTML(t *testing.T) {
111 var c C
112 var ct CText
113 var tagStruct struct {
114 Valid int `json:"<>&#! "`
115 Invalid int `json:"\\"`
116 }
117
118
119
120
121 marshalerStruct := &struct {
122 NonPtr strMarshaler
123 Ptr strPtrMarshaler
124 }{`"<str>"`, `"<str>"`}
125
126
127 stringOption := struct {
128 Bar string `json:"bar,string"`
129 }{`<html>foobar</html>`}
130
131 for _, tt := range []struct {
132 name string
133 v interface{}
134 wantEscape string
135 want string
136 }{
137 {"c", c, `"\u003c\u0026\u003e"`, `"<&>"`},
138 {"ct", ct, `"\"\u003c\u0026\u003e\""`, `"\"<&>\""`},
139 {`"<&>"`, "<&>", `"\u003c\u0026\u003e"`, `"<&>"`},
140 {
141 "tagStruct", tagStruct,
142 `{"\u003c\u003e\u0026#! ":0,"Invalid":0}`,
143 `{"<>&#! ":0,"Invalid":0}`,
144 },
145 {
146 `"<str>"`, marshalerStruct,
147 `{"NonPtr":"\u003cstr\u003e","Ptr":"\u003cstr\u003e"}`,
148 `{"NonPtr":"<str>","Ptr":"<str>"}`,
149 },
150 {
151 "stringOption", stringOption,
152 `{"bar":"\"\\u003chtml\\u003efoobar\\u003c/html\\u003e\""}`,
153 `{"bar":"\"<html>foobar</html>\""}`,
154 },
155 } {
156 var buf bytes.Buffer
157 enc := json.NewEncoder(&buf)
158 if err := enc.Encode(tt.v); err != nil {
159 t.Errorf("Encode(%s): %s", tt.name, err)
160 continue
161 }
162 if got := strings.TrimSpace(buf.String()); got != tt.wantEscape {
163 t.Errorf("Encode(%s) = %#q, want %#q", tt.name, got, tt.wantEscape)
164 }
165 buf.Reset()
166 enc.SetEscapeHTML(false)
167 if err := enc.Encode(tt.v); err != nil {
168 t.Errorf("SetEscapeHTML(false) Encode(%s): %s", tt.name, err)
169 continue
170 }
171 if got := strings.TrimSpace(buf.String()); got != tt.want {
172 t.Errorf("SetEscapeHTML(false) Encode(%s) = %#q, want %#q",
173 tt.name, got, tt.want)
174 }
175 }
176 }
177
178 func nlines(s string, n int) string {
179 if n <= 0 {
180 return ""
181 }
182 for i, c := range s {
183 if c == '\n' {
184 if n--; n == 0 {
185 return s[0 : i+1]
186 }
187 }
188 }
189 return s
190 }
191
192 func TestDecoder(t *testing.T) {
193 for i := 0; i <= len(streamTest); i++ {
194
195
196
197
198
199 var buf bytes.Buffer
200 for _, c := range nlines(streamEncoded, i) {
201 if c != '\n' {
202 buf.WriteRune(c)
203 }
204 }
205 out := make([]interface{}, i)
206 dec := json.NewDecoder(&buf)
207 for j := range out {
208 if err := dec.Decode(&out[j]); err != nil {
209 t.Fatalf("decode #%d/%d: %v", j, i, err)
210 }
211 }
212 if !reflect.DeepEqual(out, streamTest[0:i]) {
213 t.Errorf("decoding %d items: mismatch", i)
214 for j := range out {
215 if !reflect.DeepEqual(out[j], streamTest[j]) {
216 t.Errorf("#%d: have %v want %v", j, out[j], streamTest[j])
217 }
218 }
219 break
220 }
221 }
222 }
223
224 func TestDecoderBuffered(t *testing.T) {
225 r := strings.NewReader(`{"Name": "Gopher"} extra `)
226 var m struct {
227 Name string
228 }
229 d := json.NewDecoder(r)
230 err := d.Decode(&m)
231 if err != nil {
232 t.Fatal(err)
233 }
234 if m.Name != "Gopher" {
235 t.Errorf("Name = %q; want Gopher", m.Name)
236 }
237 rest, err := ioutil.ReadAll(d.Buffered())
238 if err != nil {
239 t.Fatal(err)
240 }
241 if g, w := string(rest), " extra "; g != w {
242 t.Errorf("Remaining = %q; want %q", g, w)
243 }
244 }
245
246 func TestRawMessage(t *testing.T) {
247 var data struct {
248 X float64
249 Id json.RawMessage
250 Y float32
251 }
252 const raw = `["\u0056",null]`
253 const msg = `{"X":0.1,"Id":["\u0056",null],"Y":0.2}`
254 err := json.Unmarshal([]byte(msg), &data)
255 if err != nil {
256 t.Fatalf("Unmarshal: %v", err)
257 }
258 if string([]byte(data.Id)) != raw {
259 t.Fatalf("Raw mismatch: have %#q want %#q", []byte(data.Id), raw)
260 }
261 b, err := json.Marshal(&data)
262 if err != nil {
263 t.Fatalf("Marshal: %v", err)
264 }
265 if string(b) != msg {
266 t.Fatalf("Marshal: have %#q want %#q", b, msg)
267 }
268 }
269
270 func TestNullRawMessage(t *testing.T) {
271 var data struct {
272 X float64
273 Id json.RawMessage
274 IdPtr *json.RawMessage
275 Y float32
276 }
277 const msg = `{"X":0.1,"Id":null,"IdPtr":null,"Y":0.2}`
278 err := json.Unmarshal([]byte(msg), &data)
279 if err != nil {
280 t.Fatalf("Unmarshal: %v", err)
281 }
282 if want, got := "null", string(data.Id); want != got {
283 t.Fatalf("Raw mismatch: have %q, want %q", got, want)
284 }
285 if data.IdPtr != nil {
286 t.Fatalf("Raw pointer mismatch: have non-nil, want nil")
287 }
288 b, err := json.Marshal(&data)
289 if err != nil {
290 t.Fatalf("Marshal: %v", err)
291 }
292 if string(b) != msg {
293 t.Fatalf("Marshal: have %#q want %#q", b, msg)
294 }
295 }
296
297 var blockingTests = []string{
298 `{"x": 1}`,
299 `[1, 2, 3]`,
300 }
301
302 func TestBlocking(t *testing.T) {
303 for _, enc := range blockingTests {
304 r, w := net.Pipe()
305 go w.Write([]byte(enc))
306 var val interface{}
307
308
309
310 if err := json.NewDecoder(r).Decode(&val); err != nil {
311 t.Errorf("decoding %s: %v", enc, err)
312 }
313 r.Close()
314 w.Close()
315 }
316 }
317
318 type tokenStreamCase struct {
319 json string
320 expTokens []interface{}
321 }
322
323 type decodeThis struct {
324 v interface{}
325 }
326
327 var tokenStreamCases = []tokenStreamCase{
328
329 {json: `10`, expTokens: []interface{}{float64(10)}},
330 {json: ` [10] `, expTokens: []interface{}{
331 json.Delim('['), float64(10), json.Delim(']')}},
332 {json: ` [false,10,"b"] `, expTokens: []interface{}{
333 json.Delim('['), false, float64(10), "b", json.Delim(']')}},
334 {json: `{ "a": 1 }`, expTokens: []interface{}{
335 json.Delim('{'), "a", float64(1), json.Delim('}')}},
336 {json: `{"a": 1, "b":"3"}`, expTokens: []interface{}{
337 json.Delim('{'), "a", float64(1), "b", "3", json.Delim('}')}},
338 {json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{
339 json.Delim('['),
340 json.Delim('{'), "a", float64(1), json.Delim('}'),
341 json.Delim('{'), "a", float64(2), json.Delim('}'),
342 json.Delim(']')}},
343 {json: `{"obj": {"a": 1}}`, expTokens: []interface{}{
344 json.Delim('{'), "obj", json.Delim('{'), "a", float64(1), json.Delim('}'),
345 json.Delim('}')}},
346 {json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{
347 json.Delim('{'), "obj", json.Delim('['),
348 json.Delim('{'), "a", float64(1), json.Delim('}'),
349 json.Delim(']'), json.Delim('}')}},
350
351
352 {json: `{ "a": 1 }`, expTokens: []interface{}{
353 json.Delim('{'), "a",
354 decodeThis{float64(1)},
355 json.Delim('}')}},
356 {json: ` [ { "a" : 1 } ] `, expTokens: []interface{}{
357 json.Delim('['),
358 decodeThis{map[string]interface{}{"a": float64(1)}},
359 json.Delim(']')}},
360 {json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{
361 json.Delim('['),
362 decodeThis{map[string]interface{}{"a": float64(1)}},
363 decodeThis{map[string]interface{}{"a": float64(2)}},
364 json.Delim(']')}},
365 {json: `{ "obj" : [ { "a" : 1 } ] }`, expTokens: []interface{}{
366 json.Delim('{'), "obj", json.Delim('['),
367 decodeThis{map[string]interface{}{"a": float64(1)}},
368 json.Delim(']'), json.Delim('}')}},
369
370 {json: `{"obj": {"a": 1}}`, expTokens: []interface{}{
371 json.Delim('{'), "obj",
372 decodeThis{map[string]interface{}{"a": float64(1)}},
373 json.Delim('}')}},
374 {json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{
375 json.Delim('{'), "obj",
376 decodeThis{[]interface{}{
377 map[string]interface{}{"a": float64(1)},
378 }},
379 json.Delim('}')}},
380
398 }
399
400 func TestDecodeInStream(t *testing.T) {
401 for ci, tcase := range tokenStreamCases {
402
403 dec := json.NewDecoder(strings.NewReader(tcase.json))
404 for i, etk := range tcase.expTokens {
405
406 var tk interface{}
407 var err error
408
409 if dt, ok := etk.(decodeThis); ok {
410 etk = dt.v
411 err = dec.Decode(&tk)
412 } else {
413 tk, err = dec.Token()
414 }
415 if experr, ok := etk.(error); ok {
416 if err == nil || !reflect.DeepEqual(err, experr) {
417 t.Errorf("case %v: Expected error %#v in %q, but was %#v", ci, experr, tcase.json, err)
418 }
419 break
420 } else if err == io.EOF {
421 t.Errorf("case %v: Unexpected EOF in %q", ci, tcase.json)
422 break
423 } else if err != nil {
424 t.Errorf("case %v: Unexpected error '%#v' in %q", ci, err, tcase.json)
425 break
426 }
427 if !reflect.DeepEqual(tk, etk) {
428 t.Errorf(`case %v: %q @ %v expected %T(%v) was %T(%v)`, ci, tcase.json, i, etk, etk, tk, tk)
429 break
430 }
431 }
432 }
433 }
434
435 func TestDecodeStreamUseNumber(t *testing.T) {
436 dec := json.NewDecoder(strings.NewReader(`3.14`))
437 dec.UseNumber()
438 v, err := dec.Token()
439 if err != nil {
440 t.Errorf("unexpected error: %#v", err)
441 }
442 assertEq(t, "json.Number", "json.Number", fmt.Sprintf("%T", v))
443 }
444
445
446 func TestHTTPDecoding(t *testing.T) {
447 const raw = `{ "foo": "bar" }`
448
449 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
450 w.Write([]byte(raw))
451 }))
452 defer ts.Close()
453 res, err := http.Get(ts.URL)
454 if err != nil {
455 log.Fatalf("GET failed: %v", err)
456 }
457 defer res.Body.Close()
458
459 foo := struct {
460 Foo string
461 }{}
462
463 d := json.NewDecoder(res.Body)
464 err = d.Decode(&foo)
465 if err != nil {
466 t.Fatalf("Decode: %v", err)
467 }
468 if foo.Foo != "bar" {
469 t.Errorf("decoded %q; want \"bar\"", foo.Foo)
470 }
471
472
473 err = d.Decode(&foo)
474 if err != io.EOF {
475 t.Errorf("err = %v; want io.EOF", err)
476 }
477 }
478
479 func TestGzipStreaming(t *testing.T) {
480 type someStruct struct {
481 ID int `json:"id"`
482 Text []string `json:"text"`
483 }
484
485 manyItems := strings.Repeat(`"Quis autem vel eum iure reprehenderit, qui in ea voluptate velit esse, quam`+
486 ` nihil molestiae consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla pariatur?",`, 400)
487
488 longJSON := `{"id":123,"text":[` + manyItems[0:len(manyItems)-1] + `]}`
489
490 compressed := bytes.NewBuffer(nil)
491 gw := gzip.NewWriter(compressed)
492
493 _, err := io.Copy(gw, bytes.NewReader([]byte(longJSON)))
494 if err != nil {
495 t.Fatalf("Unexpected error: %v", err)
496 }
497
498 err = gw.Close()
499 if err != nil {
500 t.Fatalf("Unexpected error: %v", err)
501 }
502
503 gr, err := gzip.NewReader(bytes.NewReader(compressed.Bytes()))
504 if err != nil {
505 t.Fatalf("Unexpected error: %v", err)
506 }
507
508 var v someStruct
509 dec := json.NewDecoder(gr)
510
511 err = dec.Decode(&v)
512 if err != nil {
513 t.Fatalf("Unexpected error: %v", err)
514 }
515 }
516
517 func TestLongUTF8(t *testing.T) {
518 want := strings.Repeat("あ", 342)
519 r := strings.NewReader(strconv.Quote(want))
520
521 var got string
522 if err := json.NewDecoder(r).Decode(&got); err != nil {
523 t.Fatalf("Unexpected error: %v", err)
524 }
525 if got != want {
526 t.Errorf("string %q; want = %q", got, want)
527 }
528 }
529
530 func TestIssue278(t *testing.T) {
531 a := `{"嗷嗷":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\u55f7"}`
532 r := strings.NewReader(a)
533 var m map[string]string
534 if err := json.NewDecoder(r).Decode(&m); err != nil {
535 t.Fatalf("Unexpected error: %v", err)
536 }
537 want := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\u55f7"
538 if got := m["嗷嗷"]; got != want {
539 t.Errorf("string %q; want = %q", got, want)
540 }
541 }
542
View as plain text