1
2
3
4
5 package json
6
7 import (
8 "bytes"
9 "encoding"
10 "fmt"
11 "image"
12 "net"
13 "reflect"
14 "strings"
15 "testing"
16 "time"
17 )
18
19 type T struct {
20 X string
21 Y int
22 Z int `json:"-"`
23 }
24
25 type U struct {
26 Alphabet string `json:"alpha"`
27 }
28
29 type V struct {
30 F1 interface{}
31 F2 int32
32 F3 Number
33 }
34
35
36
37 var ifaceNumAsFloat64 = map[string]interface{}{
38 "k1": float64(1),
39 "k2": "s",
40 "k3": []interface{}{float64(1), float64(2.0), float64(3e-3)},
41 "k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)},
42 }
43
44 var ifaceNumAsNumber = map[string]interface{}{
45 "k1": Number("1"),
46 "k2": "s",
47 "k3": []interface{}{Number("1"), Number("2.0"), Number("3e-3")},
48 "k4": map[string]interface{}{"kk1": "s", "kk2": Number("2")},
49 }
50
51 type tx struct {
52 x int
53 }
54
55
56
57 type unmarshaler struct {
58 T bool
59 }
60
61 func (u *unmarshaler) UnmarshalJSON(b []byte) error {
62 *u = unmarshaler{true}
63 return nil
64 }
65
66 type ustruct struct {
67 M unmarshaler
68 }
69
70 type unmarshalerText struct {
71 T bool
72 }
73
74
75 func (u *unmarshalerText) MarshalText() ([]byte, error) {
76 return []byte(""), nil
77 }
78
79 func (u *unmarshalerText) UnmarshalText(b []byte) error {
80 *u = unmarshalerText{true}
81 return nil
82 }
83
84 var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil)
85
86 type ustructText struct {
87 M unmarshalerText
88 }
89
90 var (
91 um0, um1 unmarshaler
92 ump = &um1
93 umtrue = unmarshaler{true}
94 umslice = []unmarshaler{{true}}
95 umslicep = new([]unmarshaler)
96 umstruct = ustruct{unmarshaler{true}}
97
98 um0T, um1T unmarshalerText
99 umpT = &um1T
100 umtrueT = unmarshalerText{true}
101 umsliceT = []unmarshalerText{{true}}
102 umslicepT = new([]unmarshalerText)
103 umstructT = ustructText{unmarshalerText{true}}
104 )
105
106
107
108 type Point struct {
109 Z int
110 }
111
112 type Top struct {
113 Level0 int
114 Embed0
115 *Embed0a
116 *Embed0b `json:"e,omitempty"`
117 Embed0c `json:"-"`
118 Loop
119 Embed0p
120 Embed0q
121 embed
122 }
123
124 type Embed0 struct {
125 Level1a int
126 Level1b int
127 Level1c int
128 Level1d int
129 Level1e int `json:"x"`
130 }
131
132 type Embed0a struct {
133 Level1a int `json:"Level1a,omitempty"`
134 Level1b int `json:"LEVEL1B,omitempty"`
135 Level1c int `json:"-"`
136 Level1d int
137 Level1f int `json:"x"`
138 }
139
140 type Embed0b Embed0
141
142 type Embed0c Embed0
143
144 type Embed0p struct {
145 image.Point
146 }
147
148 type Embed0q struct {
149 Point
150 }
151
152 type embed struct {
153 Q int
154 }
155
156 type Loop struct {
157 Loop1 int `json:",omitempty"`
158 Loop2 int `json:",omitempty"`
159 *Loop
160 }
161
162
163
164 type S5 struct {
165 S6
166 S7
167 S8
168 }
169
170 type S6 struct {
171 X int
172 }
173
174 type S7 S6
175
176 type S8 struct {
177 S9
178 }
179
180 type S9 struct {
181 X int
182 Y int
183 }
184
185
186
187 type S10 struct {
188 S11
189 S12
190 S13
191 }
192
193 type S11 struct {
194 S6
195 }
196
197 type S12 struct {
198 S6
199 }
200
201 type S13 struct {
202 S8
203 }
204
205 type unmarshalTest struct {
206 in string
207 ptr interface{}
208 out interface{}
209 err error
210 numberType NumberUnmarshalType
211 }
212
213 type XYZ struct {
214 X interface{}
215 Y interface{}
216 Z interface{}
217 }
218
219 func sliceAddr(x []int) *[]int { return &x }
220 func mapAddr(x map[string]int) *map[string]int { return &x }
221
222 var unmarshalTests = []unmarshalTest{
223
224 {in: `true`, ptr: new(bool), out: true},
225 {in: `1`, ptr: new(int), out: 1},
226 {in: `1.2`, ptr: new(float64), out: 1.2},
227 {in: `-5`, ptr: new(int16), out: int16(-5)},
228 {in: `2`, ptr: new(Number), out: Number("2"), numberType: UnmarshalJSONNumber},
229 {in: `2`, ptr: new(Number), out: Number("2")},
230 {in: `2`, ptr: new(interface{}), out: float64(2.0)},
231 {in: `2`, ptr: new(interface{}), out: Number("2"), numberType: UnmarshalJSONNumber},
232 {in: `2`, ptr: new(interface{}), out: int64(2), numberType: UnmarshalIntOrFloat},
233 {in: `2.1`, ptr: new(interface{}), out: float64(2.1), numberType: UnmarshalIntOrFloat},
234 {in: `1.5e2`, ptr: new(interface{}), out: int64(150), numberType: UnmarshalIntOrFloat},
235 {in: `9223372036854775807`, ptr: new(interface{}), out: int64(9223372036854775807), numberType: UnmarshalIntOrFloat},
236 {in: `9007199254740992.000000`, ptr: new(interface{}), out: int64(9007199254740992), numberType: UnmarshalIntOrFloat},
237 {in: `"a\u1234"`, ptr: new(string), out: "a\u1234"},
238 {in: `"http:\/\/"`, ptr: new(string), out: "http://"},
239 {in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
240 {in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
241 {in: "null", ptr: new(interface{}), out: nil},
242 {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7}},
243 {in: `{"x": 1}`, ptr: new(tx), out: tx{}},
244 {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
245 {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, numberType: UnmarshalJSONNumber},
246 {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64},
247 {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, numberType: UnmarshalJSONNumber},
248
249
250 {in: "\n true ", ptr: new(bool), out: true},
251 {in: "\t 1 ", ptr: new(int), out: 1},
252 {in: "\r 1.2 ", ptr: new(float64), out: 1.2},
253 {in: "\t -5 \n", ptr: new(int16), out: int16(-5)},
254 {in: "\t \"a\\u1234\" \n", ptr: new(string), out: "a\u1234"},
255
256
257 {in: `{"Y": 1, "Z": 2}`, ptr: new(T), out: T{Y: 1}},
258
259 {in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), out: U{Alphabet: "abc"}},
260 {in: `{"alpha": "abc"}`, ptr: new(U), out: U{Alphabet: "abc"}},
261 {in: `{"alphabet": "xyz"}`, ptr: new(U), out: U{}},
262
263
264 {in: `{"X": "foo", "Y"}`, err: &SyntaxError{"invalid character '}' after object key", 17}},
265 {in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}},
266 {in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, numberType: UnmarshalJSONNumber},
267
268
269 {in: "\x01 42", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
270 {in: " 42 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 5}},
271 {in: "\x01 true", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
272 {in: " false \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 8}},
273 {in: "\x01 1.2", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
274 {in: " 3.4 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 6}},
275 {in: "\x01 \"string\"", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
276 {in: " \"string\" \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 11}},
277
278
279 {in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}},
280 {in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}},
281 {in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}},
282
283
284 {in: `[]`, ptr: new([]interface{}), out: []interface{}{}},
285 {in: `null`, ptr: new([]interface{}), out: []interface{}(nil)},
286 {in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}},
287 {in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}},
288
289
290 {in: allValueIndent, ptr: new(All), out: allValue},
291 {in: allValueCompact, ptr: new(All), out: allValue},
292 {in: allValueIndent, ptr: new(*All), out: &allValue},
293 {in: allValueCompact, ptr: new(*All), out: &allValue},
294 {in: pallValueIndent, ptr: new(All), out: pallValue},
295 {in: pallValueCompact, ptr: new(All), out: pallValue},
296 {in: pallValueIndent, ptr: new(*All), out: &pallValue},
297 {in: pallValueCompact, ptr: new(*All), out: &pallValue},
298
299
300 {in: `{"T":false}`, ptr: &um0, out: umtrue},
301 {in: `{"T":false}`, ptr: &ump, out: &umtrue},
302 {in: `[{"T":false}]`, ptr: &umslice, out: umslice},
303 {in: `[{"T":false}]`, ptr: &umslicep, out: &umslice},
304 {in: `{"M":{"T":false}}`, ptr: &umstruct, out: umstruct},
305
306
307 {in: `"X"`, ptr: &um0T, out: umtrueT},
308 {in: `"X"`, ptr: &umpT, out: &umtrueT},
309 {in: `["X"]`, ptr: &umsliceT, out: umsliceT},
310 {in: `["X"]`, ptr: &umslicepT, out: &umsliceT},
311 {in: `{"M":"X"}`, ptr: &umstructT, out: umstructT},
312
313
314
315
316 {in: `[2]`, ptr: sliceAddr([]int{1}), out: []int{2}},
317 {in: `{"key": 2}`, ptr: mapAddr(map[string]int{"old": 0, "key": 1}), out: map[string]int{"key": 2}},
318
319 {
320 in: `{
321 "Level0": 1,
322 "Level1b": 2,
323 "Level1c": 3,
324 "x": 4,
325 "Level1a": 5,
326 "LEVEL1B": 6,
327 "e": {
328 "Level1a": 8,
329 "Level1b": 9,
330 "Level1c": 10,
331 "Level1d": 11,
332 "x": 12
333 },
334 "Loop1": 13,
335 "Loop2": 14,
336 "X": 15,
337 "Y": 16,
338 "Z": 17,
339 "Q": 18
340 }`,
341 ptr: new(Top),
342 out: Top{
343 Level0: 1,
344 Embed0: Embed0{
345 Level1b: 2,
346 Level1c: 3,
347 },
348 Embed0a: &Embed0a{
349 Level1a: 5,
350 Level1b: 6,
351 },
352 Embed0b: &Embed0b{
353 Level1a: 8,
354 Level1b: 9,
355 Level1c: 10,
356 Level1d: 11,
357 Level1e: 12,
358 },
359 Loop: Loop{
360 Loop1: 13,
361 Loop2: 14,
362 },
363 Embed0p: Embed0p{
364 Point: image.Point{X: 15, Y: 16},
365 },
366 Embed0q: Embed0q{
367 Point: Point{Z: 17},
368 },
369 embed: embed{
370 Q: 18,
371 },
372 },
373 },
374 {
375 in: `{"X": 1,"Y":2}`,
376 ptr: new(S5),
377 out: S5{S8: S8{S9: S9{Y: 2}}},
378 },
379 {
380 in: `{"X": 1,"Y":2}`,
381 ptr: new(S10),
382 out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}},
383 },
384
385
386 {
387 in: "\"hello\xffworld\"",
388 ptr: new(string),
389 out: "hello\ufffdworld",
390 },
391 {
392 in: "\"hello\xc2\xc2world\"",
393 ptr: new(string),
394 out: "hello\ufffd\ufffdworld",
395 },
396 {
397 in: "\"hello\xc2\xffworld\"",
398 ptr: new(string),
399 out: "hello\ufffd\ufffdworld",
400 },
401 {
402 in: "\"hello\\ud800world\"",
403 ptr: new(string),
404 out: "hello\ufffdworld",
405 },
406 {
407 in: "\"hello\\ud800\\ud800world\"",
408 ptr: new(string),
409 out: "hello\ufffd\ufffdworld",
410 },
411 {
412 in: "\"hello\\ud800\\ud800world\"",
413 ptr: new(string),
414 out: "hello\ufffd\ufffdworld",
415 },
416 {
417 in: "\"hello\xed\xa0\x80\xed\xb0\x80world\"",
418 ptr: new(string),
419 out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld",
420 },
421
422
423 {
424 in: `{"2009-11-10T23:00:00Z": "hello world"}`,
425 ptr: &map[time.Time]string{},
426 err: &UnmarshalTypeError{"object", reflect.TypeOf(map[time.Time]string{}), 1},
427 },
428 }
429
430 func TestMarshal(t *testing.T) {
431 b, err := Marshal(allValue)
432 if err != nil {
433 t.Fatalf("Marshal allValue: %v", err)
434 }
435 if string(b) != allValueCompact {
436 t.Errorf("Marshal allValueCompact")
437 diff(t, b, []byte(allValueCompact))
438 return
439 }
440
441 b, err = Marshal(pallValue)
442 if err != nil {
443 t.Fatalf("Marshal pallValue: %v", err)
444 }
445 if string(b) != pallValueCompact {
446 t.Errorf("Marshal pallValueCompact")
447 diff(t, b, []byte(pallValueCompact))
448 return
449 }
450 }
451
452 var badUTF8 = []struct {
453 in, out string
454 }{
455 {"hello\xffworld", `"hello\ufffdworld"`},
456 {"", `""`},
457 {"\xff", `"\ufffd"`},
458 {"\xff\xff", `"\ufffd\ufffd"`},
459 {"a\xffb", `"a\ufffdb"`},
460 {"\xe6\x97\xa5\xe6\x9c\xac\xff\xaa\x9e", `"日本\ufffd\ufffd\ufffd"`},
461 }
462
463 func TestMarshalBadUTF8(t *testing.T) {
464 for _, tt := range badUTF8 {
465 b, err := Marshal(tt.in)
466 if string(b) != tt.out || err != nil {
467 t.Errorf("Marshal(%q) = %#q, %v, want %#q, nil", tt.in, b, err, tt.out)
468 }
469 }
470 }
471
472 func TestMarshalNumberZeroVal(t *testing.T) {
473 var n Number
474 out, err := Marshal(n)
475 if err != nil {
476 t.Fatal(err)
477 }
478 outStr := string(out)
479 if outStr != "0" {
480 t.Fatalf("Invalid zero val for Number: %q", outStr)
481 }
482 }
483
484 func TestMarshalEmbeds(t *testing.T) {
485 top := &Top{
486 Level0: 1,
487 Embed0: Embed0{
488 Level1b: 2,
489 Level1c: 3,
490 },
491 Embed0a: &Embed0a{
492 Level1a: 5,
493 Level1b: 6,
494 },
495 Embed0b: &Embed0b{
496 Level1a: 8,
497 Level1b: 9,
498 Level1c: 10,
499 Level1d: 11,
500 Level1e: 12,
501 },
502 Loop: Loop{
503 Loop1: 13,
504 Loop2: 14,
505 },
506 Embed0p: Embed0p{
507 Point: image.Point{X: 15, Y: 16},
508 },
509 Embed0q: Embed0q{
510 Point: Point{Z: 17},
511 },
512 embed: embed{
513 Q: 18,
514 },
515 }
516 b, err := Marshal(top)
517 if err != nil {
518 t.Fatal(err)
519 }
520 want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17,\"Q\":18}"
521 if string(b) != want {
522 t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want)
523 }
524 }
525
526 func TestUnmarshal(t *testing.T) {
527 for i, tt := range unmarshalTests {
528 var scan scanner
529 in := []byte(tt.in)
530 if err := checkValid(in, &scan); err != nil {
531 if !reflect.DeepEqual(err, tt.err) {
532 t.Errorf("#%d: checkValid: %#v", i, err)
533 continue
534 }
535 }
536 if tt.ptr == nil {
537 continue
538 }
539
540
541 v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
542 dec := NewDecoder(bytes.NewReader(in))
543 dec.SetNumberType(tt.numberType)
544 if err := dec.Decode(v.Interface()); !reflect.DeepEqual(err, tt.err) {
545 t.Errorf("#%d: %v, want %v", i, err, tt.err)
546 continue
547 } else if err != nil {
548 continue
549 }
550 if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
551 t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
552 data, _ := Marshal(v.Elem().Interface())
553 println(string(data))
554 data, _ = Marshal(tt.out)
555 println(string(data))
556 continue
557 }
558
559
560 if tt.err == nil {
561 enc, err := Marshal(v.Interface())
562 if err != nil {
563 t.Errorf("#%d: error re-marshaling: %v", i, err)
564 continue
565 }
566 vv := reflect.New(reflect.TypeOf(tt.ptr).Elem())
567 dec = NewDecoder(bytes.NewReader(enc))
568 dec.SetNumberType(tt.numberType)
569 if err := dec.Decode(vv.Interface()); err != nil {
570 t.Errorf("#%d: error re-unmarshaling %#q: %v", i, enc, err)
571 continue
572 }
573 if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) {
574 t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface())
575 t.Errorf(" In: %q", strings.Map(noSpace, string(in)))
576 t.Errorf("Marshal: %q", strings.Map(noSpace, string(enc)))
577 continue
578 }
579 }
580 }
581 }
582
583 func TestUnmarshalMarshal(t *testing.T) {
584 initBig()
585 var v interface{}
586 if err := Unmarshal(jsonBig, &v); err != nil {
587 t.Fatalf("Unmarshal: %v", err)
588 }
589 b, err := Marshal(v)
590 if err != nil {
591 t.Fatalf("Marshal: %v", err)
592 }
593 if !bytes.Equal(jsonBig, b) {
594 t.Errorf("Marshal jsonBig")
595 diff(t, b, jsonBig)
596 return
597 }
598 }
599
600 var numberTests = []struct {
601 in string
602 i int64
603 intErr string
604 f float64
605 floatErr string
606 }{
607 {in: "-1.23e1", intErr: "strconv.ParseInt: parsing \"-1.23e1\": invalid syntax", f: -1.23e1},
608 {in: "-12", i: -12, f: -12.0},
609 {in: "1e1000", intErr: "strconv.ParseInt: parsing \"1e1000\": invalid syntax", floatErr: "strconv.ParseFloat: parsing \"1e1000\": value out of range"},
610 }
611
612
613 func TestNumberAccessors(t *testing.T) {
614 for _, tt := range numberTests {
615 n := Number(tt.in)
616 if s := n.String(); s != tt.in {
617 t.Errorf("Number(%q).String() is %q", tt.in, s)
618 }
619 if i, err := n.Int64(); err == nil && tt.intErr == "" && i != tt.i {
620 t.Errorf("Number(%q).Int64() is %d", tt.in, i)
621 } else if (err == nil && tt.intErr != "") || (err != nil && err.Error() != tt.intErr) {
622 t.Errorf("Number(%q).Int64() wanted error %q but got: %v", tt.in, tt.intErr, err)
623 }
624 if f, err := n.Float64(); err == nil && tt.floatErr == "" && f != tt.f {
625 t.Errorf("Number(%q).Float64() is %g", tt.in, f)
626 } else if (err == nil && tt.floatErr != "") || (err != nil && err.Error() != tt.floatErr) {
627 t.Errorf("Number(%q).Float64() wanted error %q but got: %v", tt.in, tt.floatErr, err)
628 }
629 }
630 }
631
632 func TestLargeByteSlice(t *testing.T) {
633 s0 := make([]byte, 2000)
634 for i := range s0 {
635 s0[i] = byte(i)
636 }
637 b, err := Marshal(s0)
638 if err != nil {
639 t.Fatalf("Marshal: %v", err)
640 }
641 var s1 []byte
642 if err := Unmarshal(b, &s1); err != nil {
643 t.Fatalf("Unmarshal: %v", err)
644 }
645 if !bytes.Equal(s0, s1) {
646 t.Errorf("Marshal large byte slice")
647 diff(t, s0, s1)
648 }
649 }
650
651 type Xint struct {
652 X int
653 }
654
655 func TestUnmarshalInterface(t *testing.T) {
656 var xint Xint
657 var i interface{} = &xint
658 if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil {
659 t.Fatalf("Unmarshal: %v", err)
660 }
661 if xint.X != 1 {
662 t.Fatalf("Did not write to xint")
663 }
664 }
665
666 func TestUnmarshalPtrPtr(t *testing.T) {
667 var xint Xint
668 pxint := &xint
669 if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil {
670 t.Fatalf("Unmarshal: %v", err)
671 }
672 if xint.X != 1 {
673 t.Fatalf("Did not write to xint")
674 }
675 }
676
677 func TestEscape(t *testing.T) {
678 const input = `"foobar"<html>` + " [\u2028 \u2029]"
679 const expected = `"\"foobar\"\u003chtml\u003e [\u2028 \u2029]"`
680 b, err := Marshal(input)
681 if err != nil {
682 t.Fatalf("Marshal error: %v", err)
683 }
684 if s := string(b); s != expected {
685 t.Errorf("Encoding of [%s]:\n got [%s]\nwant [%s]", input, s, expected)
686 }
687 }
688
689
690 type WrongString struct {
691 Message string `json:"result,string"`
692 }
693
694 type wrongStringTest struct {
695 in, err string
696 }
697
698 var wrongStringTests = []wrongStringTest{
699 {`{"result":"x"}`, `json: invalid use of ,string struct tag, trying to unmarshal "x" into string`},
700 {`{"result":"foo"}`, `json: invalid use of ,string struct tag, trying to unmarshal "foo" into string`},
701 {`{"result":"123"}`, `json: invalid use of ,string struct tag, trying to unmarshal "123" into string`},
702 {`{"result":123}`, `json: invalid use of ,string struct tag, trying to unmarshal unquoted value into string`},
703 }
704
705
706
707 func TestErrorMessageFromMisusedString(t *testing.T) {
708 for n, tt := range wrongStringTests {
709 r := strings.NewReader(tt.in)
710 var s WrongString
711 err := NewDecoder(r).Decode(&s)
712 got := fmt.Sprintf("%v", err)
713 if got != tt.err {
714 t.Errorf("%d. got err = %q, want %q", n, got, tt.err)
715 }
716 }
717 }
718
719 func noSpace(c rune) rune {
720 if isSpace(byte(c)) {
721 return -1
722 }
723 return c
724 }
725
726 type All struct {
727 Bool bool
728 Int int
729 Int8 int8
730 Int16 int16
731 Int32 int32
732 Int64 int64
733 Uint uint
734 Uint8 uint8
735 Uint16 uint16
736 Uint32 uint32
737 Uint64 uint64
738 Uintptr uintptr
739 Float32 float32
740 Float64 float64
741
742 Foo string `json:"bar"`
743 Foo2 string `json:"bar2,dummyopt"`
744
745 IntStr int64 `json:",string"`
746
747 PBool *bool
748 PInt *int
749 PInt8 *int8
750 PInt16 *int16
751 PInt32 *int32
752 PInt64 *int64
753 PUint *uint
754 PUint8 *uint8
755 PUint16 *uint16
756 PUint32 *uint32
757 PUint64 *uint64
758 PUintptr *uintptr
759 PFloat32 *float32
760 PFloat64 *float64
761
762 String string
763 PString *string
764
765 Map map[string]Small
766 MapP map[string]*Small
767 PMap *map[string]Small
768 PMapP *map[string]*Small
769
770 EmptyMap map[string]Small
771 NilMap map[string]Small
772
773 Slice []Small
774 SliceP []*Small
775 PSlice *[]Small
776 PSliceP *[]*Small
777
778 EmptySlice []Small
779 NilSlice []Small
780
781 StringSlice []string
782 ByteSlice []byte
783
784 Small Small
785 PSmall *Small
786 PPSmall **Small
787
788 Interface interface{}
789 PInterface *interface{}
790
791 unexported int
792 }
793
794 type Small struct {
795 Tag string
796 }
797
798 var allValue = All{
799 Bool: true,
800 Int: 2,
801 Int8: 3,
802 Int16: 4,
803 Int32: 5,
804 Int64: 6,
805 Uint: 7,
806 Uint8: 8,
807 Uint16: 9,
808 Uint32: 10,
809 Uint64: 11,
810 Uintptr: 12,
811 Float32: 14.1,
812 Float64: 15.1,
813 Foo: "foo",
814 Foo2: "foo2",
815 IntStr: 42,
816 String: "16",
817 Map: map[string]Small{
818 "17": {Tag: "tag17"},
819 "18": {Tag: "tag18"},
820 },
821 MapP: map[string]*Small{
822 "19": {Tag: "tag19"},
823 "20": nil,
824 },
825 EmptyMap: map[string]Small{},
826 Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}},
827 SliceP: []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}},
828 EmptySlice: []Small{},
829 StringSlice: []string{"str24", "str25", "str26"},
830 ByteSlice: []byte{27, 28, 29},
831 Small: Small{Tag: "tag30"},
832 PSmall: &Small{Tag: "tag31"},
833 Interface: 5.2,
834 }
835
836 var pallValue = All{
837 PBool: &allValue.Bool,
838 PInt: &allValue.Int,
839 PInt8: &allValue.Int8,
840 PInt16: &allValue.Int16,
841 PInt32: &allValue.Int32,
842 PInt64: &allValue.Int64,
843 PUint: &allValue.Uint,
844 PUint8: &allValue.Uint8,
845 PUint16: &allValue.Uint16,
846 PUint32: &allValue.Uint32,
847 PUint64: &allValue.Uint64,
848 PUintptr: &allValue.Uintptr,
849 PFloat32: &allValue.Float32,
850 PFloat64: &allValue.Float64,
851 PString: &allValue.String,
852 PMap: &allValue.Map,
853 PMapP: &allValue.MapP,
854 PSlice: &allValue.Slice,
855 PSliceP: &allValue.SliceP,
856 PPSmall: &allValue.PSmall,
857 PInterface: &allValue.Interface,
858 }
859
860 var allValueIndent = `{
861 "Bool": true,
862 "Int": 2,
863 "Int8": 3,
864 "Int16": 4,
865 "Int32": 5,
866 "Int64": 6,
867 "Uint": 7,
868 "Uint8": 8,
869 "Uint16": 9,
870 "Uint32": 10,
871 "Uint64": 11,
872 "Uintptr": 12,
873 "Float32": 14.1,
874 "Float64": 15.1,
875 "bar": "foo",
876 "bar2": "foo2",
877 "IntStr": "42",
878 "PBool": null,
879 "PInt": null,
880 "PInt8": null,
881 "PInt16": null,
882 "PInt32": null,
883 "PInt64": null,
884 "PUint": null,
885 "PUint8": null,
886 "PUint16": null,
887 "PUint32": null,
888 "PUint64": null,
889 "PUintptr": null,
890 "PFloat32": null,
891 "PFloat64": null,
892 "String": "16",
893 "PString": null,
894 "Map": {
895 "17": {
896 "Tag": "tag17"
897 },
898 "18": {
899 "Tag": "tag18"
900 }
901 },
902 "MapP": {
903 "19": {
904 "Tag": "tag19"
905 },
906 "20": null
907 },
908 "PMap": null,
909 "PMapP": null,
910 "EmptyMap": {},
911 "NilMap": null,
912 "Slice": [
913 {
914 "Tag": "tag20"
915 },
916 {
917 "Tag": "tag21"
918 }
919 ],
920 "SliceP": [
921 {
922 "Tag": "tag22"
923 },
924 null,
925 {
926 "Tag": "tag23"
927 }
928 ],
929 "PSlice": null,
930 "PSliceP": null,
931 "EmptySlice": [],
932 "NilSlice": null,
933 "StringSlice": [
934 "str24",
935 "str25",
936 "str26"
937 ],
938 "ByteSlice": "Gxwd",
939 "Small": {
940 "Tag": "tag30"
941 },
942 "PSmall": {
943 "Tag": "tag31"
944 },
945 "PPSmall": null,
946 "Interface": 5.2,
947 "PInterface": null
948 }`
949
950 var allValueCompact = strings.Map(noSpace, allValueIndent)
951
952 var pallValueIndent = `{
953 "Bool": false,
954 "Int": 0,
955 "Int8": 0,
956 "Int16": 0,
957 "Int32": 0,
958 "Int64": 0,
959 "Uint": 0,
960 "Uint8": 0,
961 "Uint16": 0,
962 "Uint32": 0,
963 "Uint64": 0,
964 "Uintptr": 0,
965 "Float32": 0,
966 "Float64": 0,
967 "bar": "",
968 "bar2": "",
969 "IntStr": "0",
970 "PBool": true,
971 "PInt": 2,
972 "PInt8": 3,
973 "PInt16": 4,
974 "PInt32": 5,
975 "PInt64": 6,
976 "PUint": 7,
977 "PUint8": 8,
978 "PUint16": 9,
979 "PUint32": 10,
980 "PUint64": 11,
981 "PUintptr": 12,
982 "PFloat32": 14.1,
983 "PFloat64": 15.1,
984 "String": "",
985 "PString": "16",
986 "Map": null,
987 "MapP": null,
988 "PMap": {
989 "17": {
990 "Tag": "tag17"
991 },
992 "18": {
993 "Tag": "tag18"
994 }
995 },
996 "PMapP": {
997 "19": {
998 "Tag": "tag19"
999 },
1000 "20": null
1001 },
1002 "EmptyMap": null,
1003 "NilMap": null,
1004 "Slice": null,
1005 "SliceP": null,
1006 "PSlice": [
1007 {
1008 "Tag": "tag20"
1009 },
1010 {
1011 "Tag": "tag21"
1012 }
1013 ],
1014 "PSliceP": [
1015 {
1016 "Tag": "tag22"
1017 },
1018 null,
1019 {
1020 "Tag": "tag23"
1021 }
1022 ],
1023 "EmptySlice": null,
1024 "NilSlice": null,
1025 "StringSlice": null,
1026 "ByteSlice": null,
1027 "Small": {
1028 "Tag": ""
1029 },
1030 "PSmall": null,
1031 "PPSmall": {
1032 "Tag": "tag31"
1033 },
1034 "Interface": null,
1035 "PInterface": 5.2
1036 }`
1037
1038 var pallValueCompact = strings.Map(noSpace, pallValueIndent)
1039
1040 func TestRefUnmarshal(t *testing.T) {
1041 type S struct {
1042
1043 R0 Ref
1044 R1 *Ref
1045 R2 RefText
1046 R3 *RefText
1047 }
1048 want := S{
1049 R0: 12,
1050 R1: new(Ref),
1051 R2: 13,
1052 R3: new(RefText),
1053 }
1054 *want.R1 = 12
1055 *want.R3 = 13
1056
1057 var got S
1058 if err := Unmarshal([]byte(`{"R0":"ref","R1":"ref","R2":"ref","R3":"ref"}`), &got); err != nil {
1059 t.Fatalf("Unmarshal: %v", err)
1060 }
1061 if !reflect.DeepEqual(got, want) {
1062 t.Errorf("got %+v, want %+v", got, want)
1063 }
1064 }
1065
1066
1067
1068 func TestEmptyString(t *testing.T) {
1069 type T2 struct {
1070 Number1 int `json:",string"`
1071 Number2 int `json:",string"`
1072 }
1073 data := `{"Number1":"1", "Number2":""}`
1074 dec := NewDecoder(strings.NewReader(data))
1075 var t2 T2
1076 err := dec.Decode(&t2)
1077 if err == nil {
1078 t.Fatal("Decode: did not return error")
1079 }
1080 if t2.Number1 != 1 {
1081 t.Fatal("Decode: did not set Number1")
1082 }
1083 }
1084
1085
1086
1087 func TestNullString(t *testing.T) {
1088 type T struct {
1089 A int `json:",string"`
1090 B int `json:",string"`
1091 C *int `json:",string"`
1092 }
1093 data := []byte(`{"A": "1", "B": null, "C": null}`)
1094 var s T
1095 s.B = 1
1096 s.C = new(int)
1097 *s.C = 2
1098 err := Unmarshal(data, &s)
1099 if err != nil {
1100 t.Fatalf("Unmarshal: %v", err)
1101 }
1102 if s.B != 1 || s.C != nil {
1103 t.Fatalf("after Unmarshal, s.B=%d, s.C=%p, want 1, nil", s.B, s.C)
1104 }
1105 }
1106
1107 func intp(x int) *int {
1108 p := new(int)
1109 *p = x
1110 return p
1111 }
1112
1113 func intpp(x *int) **int {
1114 pp := new(*int)
1115 *pp = x
1116 return pp
1117 }
1118
1119 var interfaceSetTests = []struct {
1120 pre interface{}
1121 json string
1122 post interface{}
1123 }{
1124 {"foo", `"bar"`, "bar"},
1125 {"foo", `2`, 2.0},
1126 {"foo", `true`, true},
1127 {"foo", `null`, nil},
1128
1129 {nil, `null`, nil},
1130 {new(int), `null`, nil},
1131 {(*int)(nil), `null`, nil},
1132 {new(*int), `null`, new(*int)},
1133 {(**int)(nil), `null`, nil},
1134 {intp(1), `null`, nil},
1135 {intpp(nil), `null`, intpp(nil)},
1136 {intpp(intp(1)), `null`, intpp(nil)},
1137 }
1138
1139 func TestInterfaceSet(t *testing.T) {
1140 for _, tt := range interfaceSetTests {
1141 b := struct{ X interface{} }{tt.pre}
1142 blob := `{"X":` + tt.json + `}`
1143 if err := Unmarshal([]byte(blob), &b); err != nil {
1144 t.Errorf("Unmarshal %#q: %v", blob, err)
1145 continue
1146 }
1147 if !reflect.DeepEqual(b.X, tt.post) {
1148 t.Errorf("Unmarshal %#q into %#v: X=%#v, want %#v", blob, tt.pre, b.X, tt.post)
1149 }
1150 }
1151 }
1152
1153
1154
1155 func TestUnmarshalNulls(t *testing.T) {
1156 jsonData := []byte(`{
1157 "Bool" : null,
1158 "Int" : null,
1159 "Int8" : null,
1160 "Int16" : null,
1161 "Int32" : null,
1162 "Int64" : null,
1163 "Uint" : null,
1164 "Uint8" : null,
1165 "Uint16" : null,
1166 "Uint32" : null,
1167 "Uint64" : null,
1168 "Float32" : null,
1169 "Float64" : null,
1170 "String" : null}`)
1171
1172 nulls := All{
1173 Bool: true,
1174 Int: 2,
1175 Int8: 3,
1176 Int16: 4,
1177 Int32: 5,
1178 Int64: 6,
1179 Uint: 7,
1180 Uint8: 8,
1181 Uint16: 9,
1182 Uint32: 10,
1183 Uint64: 11,
1184 Float32: 12.1,
1185 Float64: 13.1,
1186 String: "14"}
1187
1188 err := Unmarshal(jsonData, &nulls)
1189 if err != nil {
1190 t.Errorf("Unmarshal of null values failed: %v", err)
1191 }
1192 if !nulls.Bool || nulls.Int != 2 || nulls.Int8 != 3 || nulls.Int16 != 4 || nulls.Int32 != 5 || nulls.Int64 != 6 ||
1193 nulls.Uint != 7 || nulls.Uint8 != 8 || nulls.Uint16 != 9 || nulls.Uint32 != 10 || nulls.Uint64 != 11 ||
1194 nulls.Float32 != 12.1 || nulls.Float64 != 13.1 || nulls.String != "14" {
1195
1196 t.Errorf("Unmarshal of null values affected primitives")
1197 }
1198 }
1199
1200 func TestStringKind(t *testing.T) {
1201 type stringKind string
1202
1203 var m1, m2 map[stringKind]int
1204 m1 = map[stringKind]int{
1205 "foo": 42,
1206 }
1207
1208 data, err := Marshal(m1)
1209 if err != nil {
1210 t.Errorf("Unexpected error marshaling: %v", err)
1211 }
1212
1213 err = Unmarshal(data, &m2)
1214 if err != nil {
1215 t.Errorf("Unexpected error unmarshaling: %v", err)
1216 }
1217
1218 if !reflect.DeepEqual(m1, m2) {
1219 t.Error("Items should be equal after encoding and then decoding")
1220 }
1221 }
1222
1223
1224
1225
1226 func TestByteKind(t *testing.T) {
1227 type byteKind []byte
1228
1229 a := byteKind("hello")
1230
1231 data, err := Marshal(a)
1232 if err != nil {
1233 t.Error(err)
1234 }
1235 var b byteKind
1236 err = Unmarshal(data, &b)
1237 if err != nil {
1238 t.Fatal(err)
1239 }
1240 if !reflect.DeepEqual(a, b) {
1241 t.Errorf("expected %v == %v", a, b)
1242 }
1243 }
1244
1245
1246
1247 func TestSliceOfCustomByte(t *testing.T) {
1248 type Uint8 uint8
1249
1250 a := []Uint8("hello")
1251
1252 data, err := Marshal(a)
1253 if err != nil {
1254 t.Fatal(err)
1255 }
1256 var b []Uint8
1257 err = Unmarshal(data, &b)
1258 if err != nil {
1259 t.Fatal(err)
1260 }
1261 if !reflect.DeepEqual(a, b) {
1262 t.Fatalf("expected %v == %v", a, b)
1263 }
1264 }
1265
1266 var decodeTypeErrorTests = []struct {
1267 dest interface{}
1268 src string
1269 }{
1270 {new(string), `{"user": "name"}`},
1271 {new(error), `{}`},
1272 {new(error), `[]`},
1273 {new(error), `""`},
1274 {new(error), `123`},
1275 {new(error), `true`},
1276 }
1277
1278 func TestUnmarshalTypeError(t *testing.T) {
1279 for _, item := range decodeTypeErrorTests {
1280 err := Unmarshal([]byte(item.src), item.dest)
1281 if _, ok := err.(*UnmarshalTypeError); !ok {
1282 t.Errorf("expected type error for Unmarshal(%q, type %T): got %T",
1283 item.src, item.dest, err)
1284 }
1285 }
1286 }
1287
1288 var unmarshalSyntaxTests = []string{
1289 "tru",
1290 "fals",
1291 "nul",
1292 "123e",
1293 `"hello`,
1294 `[1,2,3`,
1295 `{"key":1`,
1296 `{"key":1,`,
1297 }
1298
1299 func TestUnmarshalSyntax(t *testing.T) {
1300 var x interface{}
1301 for _, src := range unmarshalSyntaxTests {
1302 err := Unmarshal([]byte(src), &x)
1303 if _, ok := err.(*SyntaxError); !ok {
1304 t.Errorf("expected syntax error for Unmarshal(%q): got %T", src, err)
1305 }
1306 }
1307 }
1308
1309
1310
1311 type unexportedFields struct {
1312 Name string
1313 m map[string]interface{} `json:"-"`
1314 m2 map[string]interface{} `json:"abcd"`
1315 }
1316
1317 func TestUnmarshalUnexported(t *testing.T) {
1318 input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}}`
1319 want := &unexportedFields{Name: "Bob"}
1320
1321 out := &unexportedFields{}
1322 err := Unmarshal([]byte(input), out)
1323 if err != nil {
1324 t.Errorf("got error %v, expected nil", err)
1325 }
1326 if !reflect.DeepEqual(out, want) {
1327 t.Errorf("got %q, want %q", out, want)
1328 }
1329 }
1330
1331
1332
1333 type Time3339 time.Time
1334
1335 func (t *Time3339) UnmarshalJSON(b []byte) error {
1336 if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
1337 return fmt.Errorf("types: failed to unmarshal non-string value %q as an RFC 3339 time", b)
1338 }
1339 tm, err := time.Parse(time.RFC3339, string(b[1:len(b)-1]))
1340 if err != nil {
1341 return err
1342 }
1343 *t = Time3339(tm)
1344 return nil
1345 }
1346
1347 func TestUnmarshalJSONLiteralError(t *testing.T) {
1348 var t3 Time3339
1349 err := Unmarshal([]byte(`"0000-00-00T00:00:00Z"`), &t3)
1350 if err == nil {
1351 t.Fatalf("expected error; got time %v", time.Time(t3))
1352 }
1353 if !strings.Contains(err.Error(), "range") {
1354 t.Errorf("got err = %v; want out of range error", err)
1355 }
1356 }
1357
1358
1359
1360
1361 func TestSkipArrayObjects(t *testing.T) {
1362 json := `[{}]`
1363 var dest [0]interface{}
1364
1365 err := Unmarshal([]byte(json), &dest)
1366 if err != nil {
1367 t.Errorf("got error %q, want nil", err)
1368 }
1369 }
1370
1371
1372
1373 func TestPrefilled(t *testing.T) {
1374 ptrToMap := func(m map[string]interface{}) *map[string]interface{} { return &m }
1375
1376
1377 var prefillTests = []struct {
1378 in string
1379 ptr interface{}
1380 out interface{}
1381 }{
1382 {
1383 in: `{"X": 1, "Y": 2}`,
1384 ptr: &XYZ{X: float32(3), Y: int16(4), Z: 1.5},
1385 out: &XYZ{X: float64(1), Y: float64(2), Z: 1.5},
1386 },
1387 {
1388 in: `{"X": 1, "Y": 2}`,
1389 ptr: ptrToMap(map[string]interface{}{"X": float32(3), "Y": int16(4), "Z": 1.5}),
1390 out: ptrToMap(map[string]interface{}{"X": float64(1), "Y": float64(2), "Z": 1.5}),
1391 },
1392 }
1393
1394 for _, tt := range prefillTests {
1395 ptrstr := fmt.Sprintf("%v", tt.ptr)
1396 err := Unmarshal([]byte(tt.in), tt.ptr)
1397 if err != nil {
1398 t.Errorf("Unmarshal: %v", err)
1399 }
1400 if !reflect.DeepEqual(tt.ptr, tt.out) {
1401 t.Errorf("Unmarshal(%#q, %s): have %v, want %v", tt.in, ptrstr, tt.ptr, tt.out)
1402 }
1403 }
1404 }
1405
1406 var invalidUnmarshalTests = []struct {
1407 v interface{}
1408 want string
1409 }{
1410 {nil, "json: Unmarshal(nil)"},
1411 {struct{}{}, "json: Unmarshal(non-pointer struct {})"},
1412 {(*int)(nil), "json: Unmarshal(nil *int)"},
1413 }
1414
1415 func TestInvalidUnmarshal(t *testing.T) {
1416 buf := []byte(`{"a":"1"}`)
1417 for _, tt := range invalidUnmarshalTests {
1418 err := Unmarshal(buf, tt.v)
1419 if err == nil {
1420 t.Errorf("Unmarshal expecting error, got nil")
1421 continue
1422 }
1423 if got := err.Error(); got != tt.want {
1424 t.Errorf("Unmarshal = %q; want %q", got, tt.want)
1425 }
1426 }
1427 }
1428
1429 var invalidUnmarshalTextTests = []struct {
1430 v interface{}
1431 want string
1432 }{
1433 {nil, "json: Unmarshal(nil)"},
1434 {struct{}{}, "json: Unmarshal(non-pointer struct {})"},
1435 {(*int)(nil), "json: Unmarshal(nil *int)"},
1436 {new(net.IP), "json: cannot unmarshal string into Go value of type *net.IP"},
1437 }
1438
1439 func TestInvalidUnmarshalText(t *testing.T) {
1440 buf := []byte(`123`)
1441 for _, tt := range invalidUnmarshalTextTests {
1442 err := Unmarshal(buf, tt.v)
1443 if err == nil {
1444 t.Errorf("Unmarshal expecting error, got nil")
1445 continue
1446 }
1447 if got := err.Error(); got != tt.want {
1448 t.Errorf("Unmarshal = %q; want %q", got, tt.want)
1449 }
1450 }
1451 }
1452
1453
1454
1455 func TestInvalidStringOption(t *testing.T) {
1456 num := 0
1457 item := struct {
1458 T time.Time `json:",string"`
1459 M map[string]string `json:",string"`
1460 S []string `json:",string"`
1461 A [1]string `json:",string"`
1462 I interface{} `json:",string"`
1463 P *int `json:",string"`
1464 }{M: make(map[string]string), S: make([]string, 0), I: num, P: &num}
1465
1466 data, err := Marshal(item)
1467 if err != nil {
1468 t.Fatalf("Marshal: %v", err)
1469 }
1470
1471 err = Unmarshal(data, &item)
1472 if err != nil {
1473 t.Fatalf("Unmarshal: %v", err)
1474 }
1475 }
1476
View as plain text