blob: af84b1b5279e7503b679e1c748baaabc1b07d73b [file] [log] [blame]
Russ Coxdba9d622010-04-21 16:40:53 -07001// Copyright 2010 The Go Authors. All rights reserved.
Sergey 'SnakE' Gromov9d50b462009-11-30 13:55:09 -08002// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package json
6
7import (
Russ Coxdba9d622010-04-21 16:40:53 -07008 "bytes"
Russ Cox7e886742013-08-14 14:56:07 -04009 "encoding"
Augusto Romanffbd31e2016-03-08 12:41:35 -080010 "errors"
Brad Fitzpatrickf89b5742011-12-15 10:02:47 -080011 "fmt"
Russ Coxf97bfb92012-09-10 23:31:40 -040012 "image"
Caleb Sparef05c3aa2016-04-13 16:51:25 -070013 "math"
Russ Coxf444b482016-10-12 16:54:02 -040014 "math/big"
Russ Cox671bddf2015-07-14 19:31:44 -040015 "net"
Robert Griesemera3d10452009-12-15 15:35:38 -080016 "reflect"
Caleb Sparef05c3aa2016-04-13 16:51:25 -070017 "strconv"
Russ Coxdba9d622010-04-21 16:40:53 -070018 "strings"
Robert Griesemera3d10452009-12-15 15:35:38 -080019 "testing"
Russ Coxd340a892013-02-14 14:46:15 -050020 "time"
Sergey 'SnakE' Gromov9d50b462009-11-30 13:55:09 -080021)
22
Russ Cox4e5bc6a2010-05-11 14:38:55 -070023type T struct {
24 X string
25 Y int
David Symonds3be088e2011-09-15 08:09:43 +100026 Z int `json:"-"`
Russ Cox4e5bc6a2010-05-11 14:38:55 -070027}
28
David Symondsc3c8e352012-05-01 11:37:44 +100029type U struct {
30 Alphabet string `json:"alpha"`
31}
32
Jonathan Goldb7bb1e32012-06-25 17:36:09 -040033type V struct {
34 F1 interface{}
35 F2 int32
36 F3 Number
Jirka Daněkb9fd5102016-01-18 16:26:05 +010037 F4 *VOuter
38}
39
40type VOuter struct {
41 V V
Jonathan Goldb7bb1e32012-06-25 17:36:09 -040042}
43
Rob Pike357e37d2013-04-09 15:00:21 -070044// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and
Jonathan Goldb7bb1e32012-06-25 17:36:09 -040045// without UseNumber
46var ifaceNumAsFloat64 = map[string]interface{}{
47 "k1": float64(1),
48 "k2": "s",
49 "k3": []interface{}{float64(1), float64(2.0), float64(3e-3)},
50 "k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)},
51}
52
53var ifaceNumAsNumber = map[string]interface{}{
54 "k1": Number("1"),
55 "k2": "s",
56 "k3": []interface{}{Number("1"), Number("2.0"), Number("3e-3")},
57 "k4": map[string]interface{}{"kk1": "s", "kk2": Number("2")},
58}
59
Russ Coxa400b0e2010-09-28 14:40:23 -040060type tx struct {
61 x int
62}
63
Caleb Sparef05c3aa2016-04-13 16:51:25 -070064type u8 uint8
65
Rob Pikee9c901d2010-11-08 15:33:00 -080066// A type that can unmarshal itself.
67
68type unmarshaler struct {
69 T bool
70}
71
Russ Coxc2049d22011-11-01 22:04:37 -040072func (u *unmarshaler) UnmarshalJSON(b []byte) error {
Russ Cox7e886742013-08-14 14:56:07 -040073 *u = unmarshaler{true} // All we need to see that UnmarshalJSON is called.
Rob Pikee9c901d2010-11-08 15:33:00 -080074 return nil
75}
76
Russ Cox83c73462011-08-10 09:26:51 -040077type ustruct struct {
78 M unmarshaler
79}
80
Russ Cox7e886742013-08-14 14:56:07 -040081type unmarshalerText struct {
Augusto Romanffbd31e2016-03-08 12:41:35 -080082 A, B string
Russ Cox7e886742013-08-14 14:56:07 -040083}
84
85// needed for re-marshaling tests
Augusto Romanffbd31e2016-03-08 12:41:35 -080086func (u unmarshalerText) MarshalText() ([]byte, error) {
87 return []byte(u.A + ":" + u.B), nil
Russ Cox7e886742013-08-14 14:56:07 -040088}
89
90func (u *unmarshalerText) UnmarshalText(b []byte) error {
Augusto Romanffbd31e2016-03-08 12:41:35 -080091 pos := bytes.Index(b, []byte(":"))
92 if pos == -1 {
93 return errors.New("missing separator")
94 }
95 u.A, u.B = string(b[:pos]), string(b[pos+1:])
Russ Cox7e886742013-08-14 14:56:07 -040096 return nil
97}
98
99var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil)
100
101type ustructText struct {
102 M unmarshalerText
103}
104
Caleb Sparef05c3aa2016-04-13 16:51:25 -0700105// u8marshal is an integer type that can marshal/unmarshal itself.
106type u8marshal uint8
107
108func (u8 u8marshal) MarshalText() ([]byte, error) {
109 return []byte(fmt.Sprintf("u%d", u8)), nil
110}
111
112var errMissingU8Prefix = errors.New("missing 'u' prefix")
113
114func (u8 *u8marshal) UnmarshalText(b []byte) error {
115 if !bytes.HasPrefix(b, []byte{'u'}) {
116 return errMissingU8Prefix
117 }
118 n, err := strconv.Atoi(string(b[1:]))
119 if err != nil {
120 return err
121 }
122 *u8 = u8marshal(n)
123 return nil
124}
125
126var _ encoding.TextUnmarshaler = (*u8marshal)(nil)
127
Rob Pikee9c901d2010-11-08 15:33:00 -0800128var (
129 um0, um1 unmarshaler // target2 of unmarshaling
130 ump = &um1
131 umtrue = unmarshaler{true}
Robert Griesemer61650b22011-09-06 16:04:55 -0700132 umslice = []unmarshaler{{true}}
Russ Cox83c73462011-08-10 09:26:51 -0400133 umslicep = new([]unmarshaler)
134 umstruct = ustruct{unmarshaler{true}}
Russ Cox7e886742013-08-14 14:56:07 -0400135
Augusto Romanffbd31e2016-03-08 12:41:35 -0800136 um0T, um1T unmarshalerText // target2 of unmarshaling
137 umpType = &um1T
138 umtrueXY = unmarshalerText{"x", "y"}
139 umsliceXY = []unmarshalerText{{"x", "y"}}
140 umslicepType = new([]unmarshalerText)
141 umstructType = new(ustructText)
142 umstructXY = ustructText{unmarshalerText{"x", "y"}}
143
144 ummapType = map[unmarshalerText]bool{}
145 ummapXY = map[unmarshalerText]bool{unmarshalerText{"x", "y"}: true}
Rob Pikee9c901d2010-11-08 15:33:00 -0800146)
147
Russ Coxf97bfb92012-09-10 23:31:40 -0400148// Test data structures for anonymous fields.
149
150type Point struct {
151 Z int
152}
153
154type Top struct {
155 Level0 int
156 Embed0
157 *Embed0a
158 *Embed0b `json:"e,omitempty"` // treated as named
159 Embed0c `json:"-"` // ignored
160 Loop
161 Embed0p // has Point with X, Y, used
162 Embed0q // has Point with Z, used
Marcel van Lohuizena30dd9c2015-08-28 10:17:05 +0200163 embed // contains exported field
Russ Coxf97bfb92012-09-10 23:31:40 -0400164}
165
166type Embed0 struct {
167 Level1a int // overridden by Embed0a's Level1a with json tag
168 Level1b int // used because Embed0a's Level1b is renamed
169 Level1c int // used because Embed0a's Level1c is ignored
170 Level1d int // annihilated by Embed0a's Level1d
171 Level1e int `json:"x"` // annihilated by Embed0a.Level1e
172}
173
174type Embed0a struct {
175 Level1a int `json:"Level1a,omitempty"`
176 Level1b int `json:"LEVEL1B,omitempty"`
177 Level1c int `json:"-"`
178 Level1d int // annihilated by Embed0's Level1d
179 Level1f int `json:"x"` // annihilated by Embed0's Level1e
180}
181
182type Embed0b Embed0
183
184type Embed0c Embed0
185
186type Embed0p struct {
187 image.Point
188}
189
190type Embed0q struct {
191 Point
192}
193
Marcel van Lohuizena30dd9c2015-08-28 10:17:05 +0200194type embed struct {
195 Q int
196}
197
Russ Coxf97bfb92012-09-10 23:31:40 -0400198type Loop struct {
199 Loop1 int `json:",omitempty"`
200 Loop2 int `json:",omitempty"`
201 *Loop
202}
203
204// From reflect test:
205// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
206type S5 struct {
207 S6
208 S7
209 S8
210}
211
212type S6 struct {
213 X int
214}
215
216type S7 S6
217
218type S8 struct {
219 S9
220}
221
222type S9 struct {
223 X int
224 Y int
225}
226
227// From reflect test:
228// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
229type S10 struct {
230 S11
231 S12
232 S13
233}
234
235type S11 struct {
236 S6
237}
238
239type S12 struct {
240 S6
241}
242
243type S13 struct {
244 S8
245}
246
Russ Coxf97bfb92012-09-10 23:31:40 -0400247type Ambig struct {
248 // Given "hello", the first match should win.
249 First int `json:"HELLO"`
250 Second int `json:"Hello"`
251}
252
Russ Cox5d2c3a62013-09-09 19:11:05 -0400253type XYZ struct {
254 X interface{}
255 Y interface{}
256 Z interface{}
257}
258
Russ Cox749b3912015-07-14 21:32:47 -0400259func sliceAddr(x []int) *[]int { return &x }
260func mapAddr(x map[string]int) *map[string]int { return &x }
261
Russ Cox12610232016-05-23 12:21:57 -0400262type byteWithMarshalJSON byte
263
264func (b byteWithMarshalJSON) MarshalJSON() ([]byte, error) {
265 return []byte(fmt.Sprintf(`"Z%.2x"`, byte(b))), nil
266}
267
268func (b *byteWithMarshalJSON) UnmarshalJSON(data []byte) error {
269 if len(data) != 5 || data[0] != '"' || data[1] != 'Z' || data[4] != '"' {
270 return fmt.Errorf("bad quoted string")
271 }
272 i, err := strconv.ParseInt(string(data[2:4]), 16, 8)
273 if err != nil {
274 return fmt.Errorf("bad hex")
275 }
276 *b = byteWithMarshalJSON(i)
277 return nil
278}
279
280type byteWithPtrMarshalJSON byte
281
282func (b *byteWithPtrMarshalJSON) MarshalJSON() ([]byte, error) {
283 return byteWithMarshalJSON(*b).MarshalJSON()
284}
285
286func (b *byteWithPtrMarshalJSON) UnmarshalJSON(data []byte) error {
287 return (*byteWithMarshalJSON)(b).UnmarshalJSON(data)
288}
289
290type byteWithMarshalText byte
291
292func (b byteWithMarshalText) MarshalText() ([]byte, error) {
293 return []byte(fmt.Sprintf(`Z%.2x`, byte(b))), nil
294}
295
296func (b *byteWithMarshalText) UnmarshalText(data []byte) error {
297 if len(data) != 3 || data[0] != 'Z' {
298 return fmt.Errorf("bad quoted string")
299 }
300 i, err := strconv.ParseInt(string(data[1:3]), 16, 8)
301 if err != nil {
302 return fmt.Errorf("bad hex")
303 }
304 *b = byteWithMarshalText(i)
305 return nil
306}
307
308type byteWithPtrMarshalText byte
309
310func (b *byteWithPtrMarshalText) MarshalText() ([]byte, error) {
311 return byteWithMarshalText(*b).MarshalText()
312}
313
314func (b *byteWithPtrMarshalText) UnmarshalText(data []byte) error {
315 return (*byteWithMarshalText)(b).UnmarshalText(data)
316}
317
318type intWithMarshalJSON int
319
320func (b intWithMarshalJSON) MarshalJSON() ([]byte, error) {
321 return []byte(fmt.Sprintf(`"Z%.2x"`, int(b))), nil
322}
323
324func (b *intWithMarshalJSON) UnmarshalJSON(data []byte) error {
325 if len(data) != 5 || data[0] != '"' || data[1] != 'Z' || data[4] != '"' {
326 return fmt.Errorf("bad quoted string")
327 }
328 i, err := strconv.ParseInt(string(data[2:4]), 16, 8)
329 if err != nil {
330 return fmt.Errorf("bad hex")
331 }
332 *b = intWithMarshalJSON(i)
333 return nil
334}
335
336type intWithPtrMarshalJSON int
337
338func (b *intWithPtrMarshalJSON) MarshalJSON() ([]byte, error) {
339 return intWithMarshalJSON(*b).MarshalJSON()
340}
341
342func (b *intWithPtrMarshalJSON) UnmarshalJSON(data []byte) error {
343 return (*intWithMarshalJSON)(b).UnmarshalJSON(data)
344}
345
346type intWithMarshalText int
347
348func (b intWithMarshalText) MarshalText() ([]byte, error) {
349 return []byte(fmt.Sprintf(`Z%.2x`, int(b))), nil
350}
351
352func (b *intWithMarshalText) UnmarshalText(data []byte) error {
353 if len(data) != 3 || data[0] != 'Z' {
354 return fmt.Errorf("bad quoted string")
355 }
356 i, err := strconv.ParseInt(string(data[1:3]), 16, 8)
357 if err != nil {
358 return fmt.Errorf("bad hex")
359 }
360 *b = intWithMarshalText(i)
361 return nil
362}
363
364type intWithPtrMarshalText int
365
366func (b *intWithPtrMarshalText) MarshalText() ([]byte, error) {
367 return intWithMarshalText(*b).MarshalText()
368}
369
370func (b *intWithPtrMarshalText) UnmarshalText(data []byte) error {
371 return (*intWithMarshalText)(b).UnmarshalText(data)
372}
373
374type unmarshalTest struct {
375 in string
376 ptr interface{}
377 out interface{}
378 err error
379 useNumber bool
380 golden bool
381}
382
Russ Cox0da30d52016-10-12 15:55:02 -0400383type B struct {
384 B bool `json:",string"`
385}
386
Russ Coxdba9d622010-04-21 16:40:53 -0700387var unmarshalTests = []unmarshalTest{
388 // basic types
Russ Coxd61707f2012-05-29 18:02:40 -0400389 {in: `true`, ptr: new(bool), out: true},
390 {in: `1`, ptr: new(int), out: 1},
391 {in: `1.2`, ptr: new(float64), out: 1.2},
392 {in: `-5`, ptr: new(int16), out: int16(-5)},
Jonathan Goldb7bb1e32012-06-25 17:36:09 -0400393 {in: `2`, ptr: new(Number), out: Number("2"), useNumber: true},
394 {in: `2`, ptr: new(Number), out: Number("2")},
395 {in: `2`, ptr: new(interface{}), out: float64(2.0)},
396 {in: `2`, ptr: new(interface{}), out: Number("2"), useNumber: true},
Russ Coxd61707f2012-05-29 18:02:40 -0400397 {in: `"a\u1234"`, ptr: new(string), out: "a\u1234"},
398 {in: `"http:\/\/"`, ptr: new(string), out: "http://"},
399 {in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
400 {in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
401 {in: "null", ptr: new(interface{}), out: nil},
Jirka Daněkb9fd5102016-01-18 16:26:05 +0100402 {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7, "T", "X"}},
Rick Arnold6e3f3af2013-01-22 17:49:07 -0500403 {in: `{"x": 1}`, ptr: new(tx), out: tx{}},
Jonathan Goldb7bb1e32012-06-25 17:36:09 -0400404 {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
405 {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true},
406 {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64},
407 {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true},
Russ Coxdba9d622010-04-21 16:40:53 -0700408
Rick Arnold60abc6b2013-01-10 17:58:45 -0800409 // raw values with whitespace
410 {in: "\n true ", ptr: new(bool), out: true},
411 {in: "\t 1 ", ptr: new(int), out: 1},
412 {in: "\r 1.2 ", ptr: new(float64), out: 1.2},
413 {in: "\t -5 \n", ptr: new(int16), out: int16(-5)},
414 {in: "\t \"a\\u1234\" \n", ptr: new(string), out: "a\u1234"},
415
David Symonds3be088e2011-09-15 08:09:43 +1000416 // Z has a "-" tag.
Russ Coxd61707f2012-05-29 18:02:40 -0400417 {in: `{"Y": 1, "Z": 2}`, ptr: new(T), out: T{Y: 1}},
David Symonds3be088e2011-09-15 08:09:43 +1000418
Russ Coxd61707f2012-05-29 18:02:40 -0400419 {in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), out: U{Alphabet: "abc"}},
420 {in: `{"alpha": "abc"}`, ptr: new(U), out: U{Alphabet: "abc"}},
421 {in: `{"alphabet": "xyz"}`, ptr: new(U), out: U{}},
David Symondsc3c8e352012-05-01 11:37:44 +1000422
Anthony Martin2db4c3d2010-08-03 17:05:00 -0700423 // syntax errors
Russ Coxd61707f2012-05-29 18:02:40 -0400424 {in: `{"X": "foo", "Y"}`, err: &SyntaxError{"invalid character '}' after object key", 17}},
425 {in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}},
Jonathan Goldb7bb1e32012-06-25 17:36:09 -0400426 {in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, useNumber: true},
Rémy Oudompheng4a4c39e2011-12-19 15:32:06 -0500427
Rick Arnold60abc6b2013-01-10 17:58:45 -0800428 // raw value errors
429 {in: "\x01 42", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
430 {in: " 42 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 5}},
431 {in: "\x01 true", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
432 {in: " false \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 8}},
433 {in: "\x01 1.2", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
434 {in: " 3.4 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 6}},
435 {in: "\x01 \"string\"", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
436 {in: " \"string\" \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 11}},
437
Rémy Oudompheng4a4c39e2011-12-19 15:32:06 -0500438 // array tests
Russ Coxd61707f2012-05-29 18:02:40 -0400439 {in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}},
440 {in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}},
441 {in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}},
Anthony Martin2db4c3d2010-08-03 17:05:00 -0700442
Andrey Mirtchovskie5793952013-01-30 09:10:32 -0800443 // empty array to interface test
444 {in: `[]`, ptr: new([]interface{}), out: []interface{}{}},
445 {in: `null`, ptr: new([]interface{}), out: []interface{}(nil)},
446 {in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}},
447 {in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}},
448
Russ Coxdba9d622010-04-21 16:40:53 -0700449 // composite tests
Russ Coxd61707f2012-05-29 18:02:40 -0400450 {in: allValueIndent, ptr: new(All), out: allValue},
451 {in: allValueCompact, ptr: new(All), out: allValue},
452 {in: allValueIndent, ptr: new(*All), out: &allValue},
453 {in: allValueCompact, ptr: new(*All), out: &allValue},
454 {in: pallValueIndent, ptr: new(All), out: pallValue},
455 {in: pallValueCompact, ptr: new(All), out: pallValue},
456 {in: pallValueIndent, ptr: new(*All), out: &pallValue},
457 {in: pallValueCompact, ptr: new(*All), out: &pallValue},
Rob Pikee9c901d2010-11-08 15:33:00 -0800458
459 // unmarshal interface test
Russ Coxd61707f2012-05-29 18:02:40 -0400460 {in: `{"T":false}`, ptr: &um0, out: umtrue}, // use "false" so test will fail if custom unmarshaler is not called
461 {in: `{"T":false}`, ptr: &ump, out: &umtrue},
462 {in: `[{"T":false}]`, ptr: &umslice, out: umslice},
463 {in: `[{"T":false}]`, ptr: &umslicep, out: &umslice},
Augusto Romanffbd31e2016-03-08 12:41:35 -0800464 {in: `{"M":{"T":"x:y"}}`, ptr: &umstruct, out: umstruct},
Russ Coxf97bfb92012-09-10 23:31:40 -0400465
Russ Cox7e886742013-08-14 14:56:07 -0400466 // UnmarshalText interface test
Augusto Romanffbd31e2016-03-08 12:41:35 -0800467 {in: `"x:y"`, ptr: &um0T, out: umtrueXY},
468 {in: `"x:y"`, ptr: &umpType, out: &umtrueXY},
469 {in: `["x:y"]`, ptr: &umsliceXY, out: umsliceXY},
470 {in: `["x:y"]`, ptr: &umslicepType, out: &umsliceXY},
471 {in: `{"M":"x:y"}`, ptr: umstructType, out: umstructXY},
472
Caleb Sparef05c3aa2016-04-13 16:51:25 -0700473 // integer-keyed map test
474 {
475 in: `{"-1":"a","0":"b","1":"c"}`,
476 ptr: new(map[int]string),
477 out: map[int]string{-1: "a", 0: "b", 1: "c"},
478 },
479 {
480 in: `{"0":"a","10":"c","9":"b"}`,
481 ptr: new(map[u8]string),
482 out: map[u8]string{0: "a", 9: "b", 10: "c"},
483 },
484 {
485 in: `{"-9223372036854775808":"min","9223372036854775807":"max"}`,
486 ptr: new(map[int64]string),
487 out: map[int64]string{math.MinInt64: "min", math.MaxInt64: "max"},
488 },
489 {
490 in: `{"18446744073709551615":"max"}`,
491 ptr: new(map[uint64]string),
492 out: map[uint64]string{math.MaxUint64: "max"},
493 },
494 {
495 in: `{"0":false,"10":true}`,
496 ptr: new(map[uintptr]bool),
497 out: map[uintptr]bool{0: false, 10: true},
498 },
499
500 // Check that MarshalText and UnmarshalText take precedence
501 // over default integer handling in map keys.
502 {
503 in: `{"u2":4}`,
504 ptr: new(map[u8marshal]int),
505 out: map[u8marshal]int{2: 4},
506 },
507 {
508 in: `{"2":4}`,
509 ptr: new(map[u8marshal]int),
510 err: errMissingU8Prefix,
511 },
512
513 // integer-keyed map errors
514 {
515 in: `{"abc":"abc"}`,
516 ptr: new(map[int]string),
Jirka Daněkb9fd5102016-01-18 16:26:05 +0100517 err: &UnmarshalTypeError{Value: "number abc", Type: reflect.TypeOf(0), Offset: 2},
Caleb Sparef05c3aa2016-04-13 16:51:25 -0700518 },
519 {
520 in: `{"256":"abc"}`,
521 ptr: new(map[uint8]string),
Jirka Daněkb9fd5102016-01-18 16:26:05 +0100522 err: &UnmarshalTypeError{Value: "number 256", Type: reflect.TypeOf(uint8(0)), Offset: 2},
Caleb Sparef05c3aa2016-04-13 16:51:25 -0700523 },
524 {
525 in: `{"128":"abc"}`,
526 ptr: new(map[int8]string),
Jirka Daněkb9fd5102016-01-18 16:26:05 +0100527 err: &UnmarshalTypeError{Value: "number 128", Type: reflect.TypeOf(int8(0)), Offset: 2},
Caleb Sparef05c3aa2016-04-13 16:51:25 -0700528 },
529 {
530 in: `{"-1":"abc"}`,
531 ptr: new(map[uint8]string),
Jirka Daněkb9fd5102016-01-18 16:26:05 +0100532 err: &UnmarshalTypeError{Value: "number -1", Type: reflect.TypeOf(uint8(0)), Offset: 2},
Caleb Sparef05c3aa2016-04-13 16:51:25 -0700533 },
534
535 // Map keys can be encoding.TextUnmarshalers.
Augusto Romanffbd31e2016-03-08 12:41:35 -0800536 {in: `{"x:y":true}`, ptr: &ummapType, out: ummapXY},
537 // If multiple values for the same key exists, only the most recent value is used.
538 {in: `{"x:y":false,"x:y":true}`, ptr: &ummapType, out: ummapXY},
Russ Cox7e886742013-08-14 14:56:07 -0400539
Russ Cox749b3912015-07-14 21:32:47 -0400540 // Overwriting of data.
541 // This is different from package xml, but it's what we've always done.
542 // Now documented and tested.
543 {in: `[2]`, ptr: sliceAddr([]int{1}), out: []int{2}},
544 {in: `{"key": 2}`, ptr: mapAddr(map[string]int{"old": 0, "key": 1}), out: map[string]int{"key": 2}},
545
Russ Coxf97bfb92012-09-10 23:31:40 -0400546 {
547 in: `{
548 "Level0": 1,
549 "Level1b": 2,
550 "Level1c": 3,
551 "x": 4,
552 "Level1a": 5,
553 "LEVEL1B": 6,
554 "e": {
555 "Level1a": 8,
556 "Level1b": 9,
557 "Level1c": 10,
558 "Level1d": 11,
559 "x": 12
560 },
561 "Loop1": 13,
562 "Loop2": 14,
563 "X": 15,
564 "Y": 16,
Marcel van Lohuizena30dd9c2015-08-28 10:17:05 +0200565 "Z": 17,
566 "Q": 18
Russ Coxf97bfb92012-09-10 23:31:40 -0400567 }`,
568 ptr: new(Top),
569 out: Top{
570 Level0: 1,
571 Embed0: Embed0{
572 Level1b: 2,
573 Level1c: 3,
574 },
575 Embed0a: &Embed0a{
576 Level1a: 5,
577 Level1b: 6,
578 },
579 Embed0b: &Embed0b{
580 Level1a: 8,
581 Level1b: 9,
582 Level1c: 10,
583 Level1d: 11,
584 Level1e: 12,
585 },
586 Loop: Loop{
587 Loop1: 13,
588 Loop2: 14,
589 },
590 Embed0p: Embed0p{
591 Point: image.Point{X: 15, Y: 16},
592 },
593 Embed0q: Embed0q{
594 Point: Point{Z: 17},
595 },
Marcel van Lohuizena30dd9c2015-08-28 10:17:05 +0200596 embed: embed{
597 Q: 18,
598 },
Russ Coxf97bfb92012-09-10 23:31:40 -0400599 },
600 },
601 {
602 in: `{"hello": 1}`,
603 ptr: new(Ambig),
604 out: Ambig{First: 1},
605 },
606
607 {
608 in: `{"X": 1,"Y":2}`,
609 ptr: new(S5),
610 out: S5{S8: S8{S9: S9{Y: 2}}},
611 },
612 {
613 in: `{"X": 1,"Y":2}`,
614 ptr: new(S10),
615 out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}},
616 },
Russ Cox30359a52013-02-14 14:56:01 -0500617
618 // invalid UTF-8 is coerced to valid UTF-8.
619 {
620 in: "\"hello\xffworld\"",
621 ptr: new(string),
622 out: "hello\ufffdworld",
623 },
624 {
625 in: "\"hello\xc2\xc2world\"",
626 ptr: new(string),
627 out: "hello\ufffd\ufffdworld",
628 },
629 {
630 in: "\"hello\xc2\xffworld\"",
631 ptr: new(string),
632 out: "hello\ufffd\ufffdworld",
633 },
634 {
635 in: "\"hello\\ud800world\"",
636 ptr: new(string),
637 out: "hello\ufffdworld",
638 },
639 {
640 in: "\"hello\\ud800\\ud800world\"",
641 ptr: new(string),
642 out: "hello\ufffd\ufffdworld",
643 },
644 {
645 in: "\"hello\\ud800\\ud800world\"",
646 ptr: new(string),
647 out: "hello\ufffd\ufffdworld",
648 },
649 {
650 in: "\"hello\xed\xa0\x80\xed\xb0\x80world\"",
651 ptr: new(string),
652 out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld",
653 },
Robert Griesemer7e8218a2014-10-01 16:24:17 -0700654
Augusto Romanffbd31e2016-03-08 12:41:35 -0800655 // Used to be issue 8305, but time.Time implements encoding.TextUnmarshaler so this works now.
Robert Griesemer7e8218a2014-10-01 16:24:17 -0700656 {
657 in: `{"2009-11-10T23:00:00Z": "hello world"}`,
658 ptr: &map[time.Time]string{},
Augusto Romanffbd31e2016-03-08 12:41:35 -0800659 out: map[time.Time]string{time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC): "hello world"},
660 },
661
662 // issue 8305
663 {
664 in: `{"2009-11-10T23:00:00Z": "hello world"}`,
665 ptr: &map[Point]string{},
Jirka Daněkb9fd5102016-01-18 16:26:05 +0100666 err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(map[Point]string{}), Offset: 1},
Augusto Romanffbd31e2016-03-08 12:41:35 -0800667 },
668 {
669 in: `{"asdf": "hello world"}`,
670 ptr: &map[unmarshaler]string{},
Jirka Daněkb9fd5102016-01-18 16:26:05 +0100671 err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(map[unmarshaler]string{}), Offset: 1},
Robert Griesemer7e8218a2014-10-01 16:24:17 -0700672 },
Russ Cox12610232016-05-23 12:21:57 -0400673
674 // related to issue 13783.
675 // Go 1.7 changed marshaling a slice of typed byte to use the methods on the byte type,
676 // similar to marshaling a slice of typed int.
677 // These tests check that, assuming the byte type also has valid decoding methods,
678 // either the old base64 string encoding or the new per-element encoding can be
679 // successfully unmarshaled. The custom unmarshalers were accessible in earlier
680 // versions of Go, even though the custom marshaler was not.
681 {
682 in: `"AQID"`,
683 ptr: new([]byteWithMarshalJSON),
684 out: []byteWithMarshalJSON{1, 2, 3},
685 },
686 {
687 in: `["Z01","Z02","Z03"]`,
688 ptr: new([]byteWithMarshalJSON),
689 out: []byteWithMarshalJSON{1, 2, 3},
690 golden: true,
691 },
692 {
693 in: `"AQID"`,
694 ptr: new([]byteWithMarshalText),
695 out: []byteWithMarshalText{1, 2, 3},
696 },
697 {
698 in: `["Z01","Z02","Z03"]`,
699 ptr: new([]byteWithMarshalText),
700 out: []byteWithMarshalText{1, 2, 3},
701 golden: true,
702 },
703 {
704 in: `"AQID"`,
705 ptr: new([]byteWithPtrMarshalJSON),
706 out: []byteWithPtrMarshalJSON{1, 2, 3},
707 },
708 {
709 in: `["Z01","Z02","Z03"]`,
710 ptr: new([]byteWithPtrMarshalJSON),
711 out: []byteWithPtrMarshalJSON{1, 2, 3},
712 golden: true,
713 },
714 {
715 in: `"AQID"`,
716 ptr: new([]byteWithPtrMarshalText),
717 out: []byteWithPtrMarshalText{1, 2, 3},
718 },
719 {
720 in: `["Z01","Z02","Z03"]`,
721 ptr: new([]byteWithPtrMarshalText),
722 out: []byteWithPtrMarshalText{1, 2, 3},
723 golden: true,
724 },
725
726 // ints work with the marshaler but not the base64 []byte case
727 {
728 in: `["Z01","Z02","Z03"]`,
729 ptr: new([]intWithMarshalJSON),
730 out: []intWithMarshalJSON{1, 2, 3},
731 golden: true,
732 },
733 {
734 in: `["Z01","Z02","Z03"]`,
735 ptr: new([]intWithMarshalText),
736 out: []intWithMarshalText{1, 2, 3},
737 golden: true,
738 },
739 {
740 in: `["Z01","Z02","Z03"]`,
741 ptr: new([]intWithPtrMarshalJSON),
742 out: []intWithPtrMarshalJSON{1, 2, 3},
743 golden: true,
744 },
745 {
746 in: `["Z01","Z02","Z03"]`,
747 ptr: new([]intWithPtrMarshalText),
748 out: []intWithPtrMarshalText{1, 2, 3},
749 golden: true,
750 },
Russ Cox92b3e362016-10-05 11:26:04 -0400751
752 {in: `0.000001`, ptr: new(float64), out: 0.000001, golden: true},
753 {in: `1e-7`, ptr: new(float64), out: 1e-7, golden: true},
754 {in: `100000000000000000000`, ptr: new(float64), out: 100000000000000000000.0, golden: true},
755 {in: `1e+21`, ptr: new(float64), out: 1e21, golden: true},
756 {in: `-0.000001`, ptr: new(float64), out: -0.000001, golden: true},
757 {in: `-1e-7`, ptr: new(float64), out: -1e-7, golden: true},
758 {in: `-100000000000000000000`, ptr: new(float64), out: -100000000000000000000.0, golden: true},
759 {in: `-1e+21`, ptr: new(float64), out: -1e21, golden: true},
760 {in: `999999999999999900000`, ptr: new(float64), out: 999999999999999900000.0, golden: true},
761 {in: `9007199254740992`, ptr: new(float64), out: 9007199254740992.0, golden: true},
762 {in: `9007199254740993`, ptr: new(float64), out: 9007199254740992.0, golden: false},
Jirka Daněkb9fd5102016-01-18 16:26:05 +0100763
764 {
765 in: `{"V": {"F2": "hello"}}`,
766 ptr: new(VOuter),
767 err: &UnmarshalTypeError{
768 Value: "string",
769 Struct: "V",
770 Field: "F2",
771 Type: reflect.TypeOf(int32(0)),
772 Offset: 20,
773 },
774 },
775 {
776 in: `{"V": {"F4": {}, "F2": "hello"}}`,
777 ptr: new(VOuter),
778 err: &UnmarshalTypeError{
779 Value: "string",
780 Struct: "V",
781 Field: "F2",
782 Type: reflect.TypeOf(int32(0)),
783 Offset: 30,
784 },
785 },
Russ Cox0da30d52016-10-12 15:55:02 -0400786
787 // issue 15146.
788 // invalid inputs in wrongStringTests below.
789 {in: `{"B":"true"}`, ptr: new(B), out: B{true}, golden: true},
790 {in: `{"B":"false"}`, ptr: new(B), out: B{false}, golden: true},
791 {in: `{"B": "maybe"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "maybe" into bool`)},
792 {in: `{"B": "tru"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "tru" into bool`)},
793 {in: `{"B": "False"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "False" into bool`)},
794 {in: `{"B": "null"}`, ptr: new(B), out: B{false}},
795 {in: `{"B": "nul"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "nul" into bool`)},
Sergey 'SnakE' Gromov9d50b462009-11-30 13:55:09 -0800796}
797
Russ Coxdba9d622010-04-21 16:40:53 -0700798func TestMarshal(t *testing.T) {
799 b, err := Marshal(allValue)
800 if err != nil {
801 t.Fatalf("Marshal allValue: %v", err)
802 }
803 if string(b) != allValueCompact {
804 t.Errorf("Marshal allValueCompact")
805 diff(t, b, []byte(allValueCompact))
806 return
807 }
Sergey 'SnakE' Gromov9d50b462009-11-30 13:55:09 -0800808
Russ Coxdba9d622010-04-21 16:40:53 -0700809 b, err = Marshal(pallValue)
810 if err != nil {
811 t.Fatalf("Marshal pallValue: %v", err)
812 }
813 if string(b) != pallValueCompact {
814 t.Errorf("Marshal pallValueCompact")
815 diff(t, b, []byte(pallValueCompact))
816 return
Sergey 'SnakE' Gromov9d50b462009-11-30 13:55:09 -0800817 }
818}
819
Russ Cox4274d072013-07-12 20:40:50 -0400820var badUTF8 = []struct {
821 in, out string
822}{
823 {"hello\xffworld", `"hello\ufffdworld"`},
824 {"", `""`},
825 {"\xff", `"\ufffd"`},
826 {"\xff\xff", `"\ufffd\ufffd"`},
827 {"a\xffb", `"a\ufffdb"`},
828 {"\xe6\x97\xa5\xe6\x9c\xac\xff\xaa\x9e", `"日本\ufffd\ufffd\ufffd"`},
829}
830
Russ Cox287e45e2010-12-13 15:51:11 -0500831func TestMarshalBadUTF8(t *testing.T) {
Russ Cox4274d072013-07-12 20:40:50 -0400832 for _, tt := range badUTF8 {
833 b, err := Marshal(tt.in)
834 if string(b) != tt.out || err != nil {
835 t.Errorf("Marshal(%q) = %#q, %v, want %#q, nil", tt.in, b, err, tt.out)
836 }
Russ Cox287e45e2010-12-13 15:51:11 -0500837 }
838}
839
Jonathan Goldb7bb1e32012-06-25 17:36:09 -0400840func TestMarshalNumberZeroVal(t *testing.T) {
841 var n Number
842 out, err := Marshal(n)
843 if err != nil {
844 t.Fatal(err)
845 }
846 outStr := string(out)
847 if outStr != "0" {
848 t.Fatalf("Invalid zero val for Number: %q", outStr)
849 }
850}
851
Brad Fitzpatrick89b5c6c2013-08-09 09:46:47 -0700852func TestMarshalEmbeds(t *testing.T) {
853 top := &Top{
854 Level0: 1,
855 Embed0: Embed0{
856 Level1b: 2,
857 Level1c: 3,
858 },
859 Embed0a: &Embed0a{
860 Level1a: 5,
861 Level1b: 6,
862 },
863 Embed0b: &Embed0b{
864 Level1a: 8,
865 Level1b: 9,
866 Level1c: 10,
867 Level1d: 11,
868 Level1e: 12,
869 },
870 Loop: Loop{
871 Loop1: 13,
872 Loop2: 14,
873 },
874 Embed0p: Embed0p{
875 Point: image.Point{X: 15, Y: 16},
876 },
877 Embed0q: Embed0q{
878 Point: Point{Z: 17},
879 },
Marcel van Lohuizena30dd9c2015-08-28 10:17:05 +0200880 embed: embed{
881 Q: 18,
882 },
Brad Fitzpatrick89b5c6c2013-08-09 09:46:47 -0700883 }
884 b, err := Marshal(top)
885 if err != nil {
886 t.Fatal(err)
887 }
Marcel van Lohuizena30dd9c2015-08-28 10:17:05 +0200888 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}"
Brad Fitzpatrick89b5c6c2013-08-09 09:46:47 -0700889 if string(b) != want {
890 t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want)
891 }
892}
893
Russ Coxdba9d622010-04-21 16:40:53 -0700894func TestUnmarshal(t *testing.T) {
Russ Coxdba9d622010-04-21 16:40:53 -0700895 for i, tt := range unmarshalTests {
Brad Fitzpatrick9b8d4e02011-04-15 08:14:34 -0700896 var scan scanner
Russ Coxdba9d622010-04-21 16:40:53 -0700897 in := []byte(tt.in)
898 if err := checkValid(in, &scan); err != nil {
Anthony Martin2db4c3d2010-08-03 17:05:00 -0700899 if !reflect.DeepEqual(err, tt.err) {
Brad Fitzpatrick9b8d4e02011-04-15 08:14:34 -0700900 t.Errorf("#%d: checkValid: %#v", i, err)
Anthony Martin2db4c3d2010-08-03 17:05:00 -0700901 continue
902 }
903 }
904 if tt.ptr == nil {
Russ Coxdba9d622010-04-21 16:40:53 -0700905 continue
906 }
Robert Griesemer7e8218a2014-10-01 16:24:17 -0700907
Russ Coxdba9d622010-04-21 16:40:53 -0700908 // v = new(right-type)
Russ Cox07abf1c2011-04-25 13:39:36 -0400909 v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
Brad Fitzpatrick89b5c6c2013-08-09 09:46:47 -0700910 dec := NewDecoder(bytes.NewReader(in))
Jonathan Goldb7bb1e32012-06-25 17:36:09 -0400911 if tt.useNumber {
912 dec.UseNumber()
913 }
914 if err := dec.Decode(v.Interface()); !reflect.DeepEqual(err, tt.err) {
Robert Griesemer7e8218a2014-10-01 16:24:17 -0700915 t.Errorf("#%d: %v, want %v", i, err, tt.err)
916 continue
917 } else if err != nil {
Russ Coxdba9d622010-04-21 16:40:53 -0700918 continue
919 }
920 if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
921 t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
922 data, _ := Marshal(v.Elem().Interface())
923 println(string(data))
924 data, _ = Marshal(tt.out)
925 println(string(data))
Russ Coxdba9d622010-04-21 16:40:53 -0700926 continue
Sergey 'SnakE' Gromov9d50b462009-11-30 13:55:09 -0800927 }
Russ Coxd61707f2012-05-29 18:02:40 -0400928
Russ Cox12610232016-05-23 12:21:57 -0400929 // Check round trip also decodes correctly.
Russ Coxd61707f2012-05-29 18:02:40 -0400930 if tt.err == nil {
931 enc, err := Marshal(v.Interface())
932 if err != nil {
933 t.Errorf("#%d: error re-marshaling: %v", i, err)
934 continue
935 }
Russ Cox12610232016-05-23 12:21:57 -0400936 if tt.golden && !bytes.Equal(enc, in) {
937 t.Errorf("#%d: remarshal mismatch:\nhave: %s\nwant: %s", i, enc, in)
938 }
Russ Coxd61707f2012-05-29 18:02:40 -0400939 vv := reflect.New(reflect.TypeOf(tt.ptr).Elem())
Brad Fitzpatrick89b5c6c2013-08-09 09:46:47 -0700940 dec = NewDecoder(bytes.NewReader(enc))
Jonathan Goldb7bb1e32012-06-25 17:36:09 -0400941 if tt.useNumber {
942 dec.UseNumber()
943 }
944 if err := dec.Decode(vv.Interface()); err != nil {
Russ Cox7e886742013-08-14 14:56:07 -0400945 t.Errorf("#%d: error re-unmarshaling %#q: %v", i, enc, err)
Russ Coxd61707f2012-05-29 18:02:40 -0400946 continue
947 }
948 if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) {
949 t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface())
Brad Fitzpatrick89b5c6c2013-08-09 09:46:47 -0700950 t.Errorf(" In: %q", strings.Map(noSpace, string(in)))
951 t.Errorf("Marshal: %q", strings.Map(noSpace, string(enc)))
Russ Coxd61707f2012-05-29 18:02:40 -0400952 continue
953 }
954 }
Sergey 'SnakE' Gromov9d50b462009-11-30 13:55:09 -0800955 }
956}
Russ Coxdba9d622010-04-21 16:40:53 -0700957
958func TestUnmarshalMarshal(t *testing.T) {
Rob Pike7f9acb52011-03-26 11:25:22 -0700959 initBig()
Russ Coxdba9d622010-04-21 16:40:53 -0700960 var v interface{}
961 if err := Unmarshal(jsonBig, &v); err != nil {
962 t.Fatalf("Unmarshal: %v", err)
963 }
964 b, err := Marshal(v)
965 if err != nil {
966 t.Fatalf("Marshal: %v", err)
967 }
Matthew Dempsky46811d22013-01-07 10:03:49 +1100968 if !bytes.Equal(jsonBig, b) {
Russ Coxdba9d622010-04-21 16:40:53 -0700969 t.Errorf("Marshal jsonBig")
970 diff(t, b, jsonBig)
971 return
972 }
973}
974
Jonathan Goldb7bb1e32012-06-25 17:36:09 -0400975var numberTests = []struct {
976 in string
977 i int64
978 intErr string
979 f float64
980 floatErr string
981}{
982 {in: "-1.23e1", intErr: "strconv.ParseInt: parsing \"-1.23e1\": invalid syntax", f: -1.23e1},
983 {in: "-12", i: -12, f: -12.0},
984 {in: "1e1000", intErr: "strconv.ParseInt: parsing \"1e1000\": invalid syntax", floatErr: "strconv.ParseFloat: parsing \"1e1000\": value out of range"},
985}
986
987// Independent of Decode, basic coverage of the accessors in Number
988func TestNumberAccessors(t *testing.T) {
989 for _, tt := range numberTests {
990 n := Number(tt.in)
991 if s := n.String(); s != tt.in {
992 t.Errorf("Number(%q).String() is %q", tt.in, s)
993 }
994 if i, err := n.Int64(); err == nil && tt.intErr == "" && i != tt.i {
995 t.Errorf("Number(%q).Int64() is %d", tt.in, i)
996 } else if (err == nil && tt.intErr != "") || (err != nil && err.Error() != tt.intErr) {
997 t.Errorf("Number(%q).Int64() wanted error %q but got: %v", tt.in, tt.intErr, err)
998 }
999 if f, err := n.Float64(); err == nil && tt.floatErr == "" && f != tt.f {
1000 t.Errorf("Number(%q).Float64() is %g", tt.in, f)
1001 } else if (err == nil && tt.floatErr != "") || (err != nil && err.Error() != tt.floatErr) {
1002 t.Errorf("Number(%q).Float64() wanted error %q but got: %v", tt.in, tt.floatErr, err)
1003 }
1004 }
1005}
1006
Roger Peppe83da7d12011-02-23 11:32:29 -05001007func TestLargeByteSlice(t *testing.T) {
1008 s0 := make([]byte, 2000)
1009 for i := range s0 {
1010 s0[i] = byte(i)
1011 }
1012 b, err := Marshal(s0)
1013 if err != nil {
1014 t.Fatalf("Marshal: %v", err)
1015 }
1016 var s1 []byte
1017 if err := Unmarshal(b, &s1); err != nil {
1018 t.Fatalf("Unmarshal: %v", err)
1019 }
Matthew Dempsky46811d22013-01-07 10:03:49 +11001020 if !bytes.Equal(s0, s1) {
Roger Peppe83da7d12011-02-23 11:32:29 -05001021 t.Errorf("Marshal large byte slice")
1022 diff(t, s0, s1)
1023 }
1024}
1025
Russ Coxbec40ba2010-04-27 10:24:00 -07001026type Xint struct {
1027 X int
1028}
1029
1030func TestUnmarshalInterface(t *testing.T) {
1031 var xint Xint
1032 var i interface{} = &xint
1033 if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil {
1034 t.Fatalf("Unmarshal: %v", err)
1035 }
1036 if xint.X != 1 {
1037 t.Fatalf("Did not write to xint")
1038 }
1039}
1040
1041func TestUnmarshalPtrPtr(t *testing.T) {
1042 var xint Xint
1043 pxint := &xint
1044 if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil {
1045 t.Fatalf("Unmarshal: %v", err)
1046 }
1047 if xint.X != 1 {
1048 t.Fatalf("Did not write to xint")
1049 }
1050}
1051
David Symondscbad5802011-07-14 13:30:08 +10001052func TestEscape(t *testing.T) {
David Symondsd7546472013-07-12 14:35:55 +10001053 const input = `"foobar"<html>` + " [\u2028 \u2029]"
1054 const expected = `"\"foobar\"\u003chtml\u003e [\u2028 \u2029]"`
David Symondscbad5802011-07-14 13:30:08 +10001055 b, err := Marshal(input)
1056 if err != nil {
1057 t.Fatalf("Marshal error: %v", err)
1058 }
1059 if s := string(b); s != expected {
David Symondsd7546472013-07-12 14:35:55 +10001060 t.Errorf("Encoding of [%s]:\n got [%s]\nwant [%s]", input, s, expected)
David Symondscbad5802011-07-14 13:30:08 +10001061 }
1062}
1063
Brad Fitzpatrickf89b5742011-12-15 10:02:47 -08001064// WrongString is a struct that's misusing the ,string modifier.
1065type WrongString struct {
1066 Message string `json:"result,string"`
1067}
1068
1069type wrongStringTest struct {
1070 in, err string
1071}
1072
Brad Fitzpatrickf89b5742011-12-15 10:02:47 -08001073var wrongStringTests = []wrongStringTest{
Brad Fitzpatrickb37de732012-01-12 14:40:29 -08001074 {`{"result":"x"}`, `json: invalid use of ,string struct tag, trying to unmarshal "x" into string`},
1075 {`{"result":"foo"}`, `json: invalid use of ,string struct tag, trying to unmarshal "foo" into string`},
1076 {`{"result":"123"}`, `json: invalid use of ,string struct tag, trying to unmarshal "123" into string`},
Emil Hessman2c987e12014-12-27 20:52:17 +01001077 {`{"result":123}`, `json: invalid use of ,string struct tag, trying to unmarshal unquoted value into string`},
Brad Fitzpatrickf89b5742011-12-15 10:02:47 -08001078}
1079
1080// If people misuse the ,string modifier, the error message should be
1081// helpful, telling the user that they're doing it wrong.
1082func TestErrorMessageFromMisusedString(t *testing.T) {
1083 for n, tt := range wrongStringTests {
1084 r := strings.NewReader(tt.in)
1085 var s WrongString
1086 err := NewDecoder(r).Decode(&s)
1087 got := fmt.Sprintf("%v", err)
1088 if got != tt.err {
1089 t.Errorf("%d. got err = %q, want %q", n, got, tt.err)
1090 }
1091 }
1092}
1093
Russ Coxb50a8472011-10-25 22:23:54 -07001094func noSpace(c rune) rune {
Marvin Stengerfcf81432015-09-21 00:45:21 +02001095 if isSpace(byte(c)) { //only used for ascii
Russ Coxdba9d622010-04-21 16:40:53 -07001096 return -1
1097 }
1098 return c
1099}
1100
1101type All struct {
1102 Bool bool
1103 Int int
1104 Int8 int8
1105 Int16 int16
1106 Int32 int32
1107 Int64 int64
1108 Uint uint
1109 Uint8 uint8
1110 Uint16 uint16
1111 Uint32 uint32
1112 Uint64 uint64
1113 Uintptr uintptr
Russ Coxdba9d622010-04-21 16:40:53 -07001114 Float32 float32
1115 Float64 float64
1116
Brad Fitzpatrick396cd362011-08-26 12:27:33 +04001117 Foo string `json:"bar"`
1118 Foo2 string `json:"bar2,dummyopt"`
Russ Coxdba9d622010-04-21 16:40:53 -07001119
Brad Fitzpatrick596bf612011-08-29 12:46:32 -07001120 IntStr int64 `json:",string"`
1121
Russ Coxdba9d622010-04-21 16:40:53 -07001122 PBool *bool
1123 PInt *int
1124 PInt8 *int8
1125 PInt16 *int16
1126 PInt32 *int32
1127 PInt64 *int64
1128 PUint *uint
1129 PUint8 *uint8
1130 PUint16 *uint16
1131 PUint32 *uint32
1132 PUint64 *uint64
1133 PUintptr *uintptr
Russ Coxdba9d622010-04-21 16:40:53 -07001134 PFloat32 *float32
1135 PFloat64 *float64
1136
1137 String string
1138 PString *string
1139
1140 Map map[string]Small
1141 MapP map[string]*Small
1142 PMap *map[string]Small
1143 PMapP *map[string]*Small
1144
1145 EmptyMap map[string]Small
1146 NilMap map[string]Small
1147
1148 Slice []Small
1149 SliceP []*Small
1150 PSlice *[]Small
1151 PSliceP *[]*Small
1152
1153 EmptySlice []Small
1154 NilSlice []Small
1155
1156 StringSlice []string
1157 ByteSlice []byte
1158
1159 Small Small
1160 PSmall *Small
1161 PPSmall **Small
1162
1163 Interface interface{}
1164 PInterface *interface{}
Andrew Gerrand09d4bcf2011-01-12 11:59:33 +11001165
1166 unexported int
Russ Coxdba9d622010-04-21 16:40:53 -07001167}
1168
1169type Small struct {
1170 Tag string
1171}
1172
1173var allValue = All{
1174 Bool: true,
1175 Int: 2,
1176 Int8: 3,
1177 Int16: 4,
1178 Int32: 5,
1179 Int64: 6,
1180 Uint: 7,
1181 Uint8: 8,
1182 Uint16: 9,
1183 Uint32: 10,
1184 Uint64: 11,
1185 Uintptr: 12,
Russ Coxdba9d622010-04-21 16:40:53 -07001186 Float32: 14.1,
1187 Float64: 15.1,
1188 Foo: "foo",
Brad Fitzpatrick396cd362011-08-26 12:27:33 +04001189 Foo2: "foo2",
Brad Fitzpatrick596bf612011-08-29 12:46:32 -07001190 IntStr: 42,
Russ Coxdba9d622010-04-21 16:40:53 -07001191 String: "16",
1192 Map: map[string]Small{
Robert Griesemer34788912010-10-22 10:06:33 -07001193 "17": {Tag: "tag17"},
1194 "18": {Tag: "tag18"},
Russ Coxdba9d622010-04-21 16:40:53 -07001195 },
1196 MapP: map[string]*Small{
Russ Coxdcf1d7b2011-12-02 14:14:25 -05001197 "19": {Tag: "tag19"},
Russ Coxdba9d622010-04-21 16:40:53 -07001198 "20": nil,
1199 },
1200 EmptyMap: map[string]Small{},
Robert Griesemer34788912010-10-22 10:06:33 -07001201 Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}},
Russ Coxdcf1d7b2011-12-02 14:14:25 -05001202 SliceP: []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}},
Russ Coxdba9d622010-04-21 16:40:53 -07001203 EmptySlice: []Small{},
1204 StringSlice: []string{"str24", "str25", "str26"},
1205 ByteSlice: []byte{27, 28, 29},
1206 Small: Small{Tag: "tag30"},
1207 PSmall: &Small{Tag: "tag31"},
Russ Coxf2b5a072011-01-19 23:09:00 -05001208 Interface: 5.2,
Russ Coxdba9d622010-04-21 16:40:53 -07001209}
1210
1211var pallValue = All{
1212 PBool: &allValue.Bool,
1213 PInt: &allValue.Int,
1214 PInt8: &allValue.Int8,
1215 PInt16: &allValue.Int16,
1216 PInt32: &allValue.Int32,
1217 PInt64: &allValue.Int64,
1218 PUint: &allValue.Uint,
1219 PUint8: &allValue.Uint8,
1220 PUint16: &allValue.Uint16,
1221 PUint32: &allValue.Uint32,
1222 PUint64: &allValue.Uint64,
1223 PUintptr: &allValue.Uintptr,
Russ Coxdba9d622010-04-21 16:40:53 -07001224 PFloat32: &allValue.Float32,
1225 PFloat64: &allValue.Float64,
1226 PString: &allValue.String,
1227 PMap: &allValue.Map,
1228 PMapP: &allValue.MapP,
1229 PSlice: &allValue.Slice,
1230 PSliceP: &allValue.SliceP,
1231 PPSmall: &allValue.PSmall,
1232 PInterface: &allValue.Interface,
1233}
1234
1235var allValueIndent = `{
Russ Coxbec40ba2010-04-27 10:24:00 -07001236 "Bool": true,
1237 "Int": 2,
1238 "Int8": 3,
1239 "Int16": 4,
1240 "Int32": 5,
1241 "Int64": 6,
1242 "Uint": 7,
1243 "Uint8": 8,
1244 "Uint16": 9,
1245 "Uint32": 10,
1246 "Uint64": 11,
1247 "Uintptr": 12,
Russ Coxbec40ba2010-04-27 10:24:00 -07001248 "Float32": 14.1,
1249 "Float64": 15.1,
Russ Coxdba9d622010-04-21 16:40:53 -07001250 "bar": "foo",
Brad Fitzpatrick396cd362011-08-26 12:27:33 +04001251 "bar2": "foo2",
Brad Fitzpatrick596bf612011-08-29 12:46:32 -07001252 "IntStr": "42",
Russ Coxbec40ba2010-04-27 10:24:00 -07001253 "PBool": null,
1254 "PInt": null,
1255 "PInt8": null,
1256 "PInt16": null,
1257 "PInt32": null,
1258 "PInt64": null,
1259 "PUint": null,
1260 "PUint8": null,
1261 "PUint16": null,
1262 "PUint32": null,
1263 "PUint64": null,
1264 "PUintptr": null,
Russ Coxbec40ba2010-04-27 10:24:00 -07001265 "PFloat32": null,
1266 "PFloat64": null,
1267 "String": "16",
1268 "PString": null,
1269 "Map": {
Russ Coxdba9d622010-04-21 16:40:53 -07001270 "17": {
Russ Coxbec40ba2010-04-27 10:24:00 -07001271 "Tag": "tag17"
Russ Coxdba9d622010-04-21 16:40:53 -07001272 },
1273 "18": {
Russ Coxbec40ba2010-04-27 10:24:00 -07001274 "Tag": "tag18"
Russ Coxdba9d622010-04-21 16:40:53 -07001275 }
1276 },
Russ Coxbec40ba2010-04-27 10:24:00 -07001277 "MapP": {
Russ Coxdba9d622010-04-21 16:40:53 -07001278 "19": {
Russ Coxbec40ba2010-04-27 10:24:00 -07001279 "Tag": "tag19"
Russ Coxdba9d622010-04-21 16:40:53 -07001280 },
1281 "20": null
1282 },
Russ Coxbec40ba2010-04-27 10:24:00 -07001283 "PMap": null,
1284 "PMapP": null,
1285 "EmptyMap": {},
1286 "NilMap": null,
1287 "Slice": [
Russ Coxdba9d622010-04-21 16:40:53 -07001288 {
Russ Coxbec40ba2010-04-27 10:24:00 -07001289 "Tag": "tag20"
Russ Coxdba9d622010-04-21 16:40:53 -07001290 },
1291 {
Russ Coxbec40ba2010-04-27 10:24:00 -07001292 "Tag": "tag21"
Russ Coxdba9d622010-04-21 16:40:53 -07001293 }
1294 ],
Russ Coxbec40ba2010-04-27 10:24:00 -07001295 "SliceP": [
Russ Coxdba9d622010-04-21 16:40:53 -07001296 {
Russ Coxbec40ba2010-04-27 10:24:00 -07001297 "Tag": "tag22"
Russ Coxdba9d622010-04-21 16:40:53 -07001298 },
1299 null,
1300 {
Russ Coxbec40ba2010-04-27 10:24:00 -07001301 "Tag": "tag23"
Russ Coxdba9d622010-04-21 16:40:53 -07001302 }
1303 ],
Russ Coxbec40ba2010-04-27 10:24:00 -07001304 "PSlice": null,
1305 "PSliceP": null,
1306 "EmptySlice": [],
Alexander Reece48c75c52011-10-31 13:59:23 -04001307 "NilSlice": null,
Russ Coxbec40ba2010-04-27 10:24:00 -07001308 "StringSlice": [
Russ Coxdba9d622010-04-21 16:40:53 -07001309 "str24",
1310 "str25",
1311 "str26"
1312 ],
Roger Peppe83da7d12011-02-23 11:32:29 -05001313 "ByteSlice": "Gxwd",
Russ Coxbec40ba2010-04-27 10:24:00 -07001314 "Small": {
1315 "Tag": "tag30"
Russ Coxdba9d622010-04-21 16:40:53 -07001316 },
Russ Coxbec40ba2010-04-27 10:24:00 -07001317 "PSmall": {
1318 "Tag": "tag31"
Russ Coxdba9d622010-04-21 16:40:53 -07001319 },
Russ Coxbec40ba2010-04-27 10:24:00 -07001320 "PPSmall": null,
1321 "Interface": 5.2,
1322 "PInterface": null
Russ Coxdba9d622010-04-21 16:40:53 -07001323}`
1324
1325var allValueCompact = strings.Map(noSpace, allValueIndent)
1326
1327var pallValueIndent = `{
Russ Coxbec40ba2010-04-27 10:24:00 -07001328 "Bool": false,
1329 "Int": 0,
1330 "Int8": 0,
1331 "Int16": 0,
1332 "Int32": 0,
1333 "Int64": 0,
1334 "Uint": 0,
1335 "Uint8": 0,
1336 "Uint16": 0,
1337 "Uint32": 0,
1338 "Uint64": 0,
1339 "Uintptr": 0,
Russ Coxbec40ba2010-04-27 10:24:00 -07001340 "Float32": 0,
1341 "Float64": 0,
Russ Coxdba9d622010-04-21 16:40:53 -07001342 "bar": "",
Brad Fitzpatrick396cd362011-08-26 12:27:33 +04001343 "bar2": "",
Brad Fitzpatrick596bf612011-08-29 12:46:32 -07001344 "IntStr": "0",
Russ Coxbec40ba2010-04-27 10:24:00 -07001345 "PBool": true,
1346 "PInt": 2,
1347 "PInt8": 3,
1348 "PInt16": 4,
1349 "PInt32": 5,
1350 "PInt64": 6,
1351 "PUint": 7,
1352 "PUint8": 8,
1353 "PUint16": 9,
1354 "PUint32": 10,
1355 "PUint64": 11,
1356 "PUintptr": 12,
Russ Coxbec40ba2010-04-27 10:24:00 -07001357 "PFloat32": 14.1,
1358 "PFloat64": 15.1,
1359 "String": "",
1360 "PString": "16",
1361 "Map": null,
1362 "MapP": null,
1363 "PMap": {
Russ Coxdba9d622010-04-21 16:40:53 -07001364 "17": {
Russ Coxbec40ba2010-04-27 10:24:00 -07001365 "Tag": "tag17"
Russ Coxdba9d622010-04-21 16:40:53 -07001366 },
1367 "18": {
Russ Coxbec40ba2010-04-27 10:24:00 -07001368 "Tag": "tag18"
Russ Coxdba9d622010-04-21 16:40:53 -07001369 }
1370 },
Russ Coxbec40ba2010-04-27 10:24:00 -07001371 "PMapP": {
Russ Coxdba9d622010-04-21 16:40:53 -07001372 "19": {
Russ Coxbec40ba2010-04-27 10:24:00 -07001373 "Tag": "tag19"
Russ Coxdba9d622010-04-21 16:40:53 -07001374 },
1375 "20": null
1376 },
Russ Coxbec40ba2010-04-27 10:24:00 -07001377 "EmptyMap": null,
1378 "NilMap": null,
Alexander Reece48c75c52011-10-31 13:59:23 -04001379 "Slice": null,
1380 "SliceP": null,
Russ Coxbec40ba2010-04-27 10:24:00 -07001381 "PSlice": [
Russ Coxdba9d622010-04-21 16:40:53 -07001382 {
Russ Coxbec40ba2010-04-27 10:24:00 -07001383 "Tag": "tag20"
Russ Coxdba9d622010-04-21 16:40:53 -07001384 },
1385 {
Russ Coxbec40ba2010-04-27 10:24:00 -07001386 "Tag": "tag21"
Russ Coxdba9d622010-04-21 16:40:53 -07001387 }
1388 ],
Russ Coxbec40ba2010-04-27 10:24:00 -07001389 "PSliceP": [
Russ Coxdba9d622010-04-21 16:40:53 -07001390 {
Russ Coxbec40ba2010-04-27 10:24:00 -07001391 "Tag": "tag22"
Russ Coxdba9d622010-04-21 16:40:53 -07001392 },
1393 null,
1394 {
Russ Coxbec40ba2010-04-27 10:24:00 -07001395 "Tag": "tag23"
Russ Coxdba9d622010-04-21 16:40:53 -07001396 }
1397 ],
Alexander Reece48c75c52011-10-31 13:59:23 -04001398 "EmptySlice": null,
1399 "NilSlice": null,
1400 "StringSlice": null,
1401 "ByteSlice": null,
Russ Coxbec40ba2010-04-27 10:24:00 -07001402 "Small": {
1403 "Tag": ""
Russ Coxdba9d622010-04-21 16:40:53 -07001404 },
Russ Coxbec40ba2010-04-27 10:24:00 -07001405 "PSmall": null,
1406 "PPSmall": {
1407 "Tag": "tag31"
Russ Coxdba9d622010-04-21 16:40:53 -07001408 },
Russ Coxbec40ba2010-04-27 10:24:00 -07001409 "Interface": null,
1410 "PInterface": 5.2
Russ Coxdba9d622010-04-21 16:40:53 -07001411}`
1412
1413var pallValueCompact = strings.Map(noSpace, pallValueIndent)
David Symondsbf89d582012-02-03 11:15:06 +11001414
1415func TestRefUnmarshal(t *testing.T) {
1416 type S struct {
1417 // Ref is defined in encode_test.go.
1418 R0 Ref
1419 R1 *Ref
Russ Cox7e886742013-08-14 14:56:07 -04001420 R2 RefText
1421 R3 *RefText
David Symondsbf89d582012-02-03 11:15:06 +11001422 }
1423 want := S{
1424 R0: 12,
1425 R1: new(Ref),
Russ Cox7e886742013-08-14 14:56:07 -04001426 R2: 13,
1427 R3: new(RefText),
David Symondsbf89d582012-02-03 11:15:06 +11001428 }
1429 *want.R1 = 12
Russ Cox7e886742013-08-14 14:56:07 -04001430 *want.R3 = 13
David Symondsbf89d582012-02-03 11:15:06 +11001431
1432 var got S
Russ Cox7e886742013-08-14 14:56:07 -04001433 if err := Unmarshal([]byte(`{"R0":"ref","R1":"ref","R2":"ref","R3":"ref"}`), &got); err != nil {
David Symondsbf89d582012-02-03 11:15:06 +11001434 t.Fatalf("Unmarshal: %v", err)
1435 }
1436 if !reflect.DeepEqual(got, want) {
1437 t.Errorf("got %+v, want %+v", got, want)
1438 }
1439}
Russ Cox990f9f42012-02-19 00:27:05 -05001440
Michael Chaten3fab2a92012-05-03 17:35:44 -04001441// Test that the empty string doesn't panic decoding when ,string is specified
1442// Issue 3450
1443func TestEmptyString(t *testing.T) {
1444 type T2 struct {
1445 Number1 int `json:",string"`
1446 Number2 int `json:",string"`
1447 }
1448 data := `{"Number1":"1", "Number2":""}`
1449 dec := NewDecoder(strings.NewReader(data))
1450 var t2 T2
1451 err := dec.Decode(&t2)
1452 if err == nil {
1453 t.Fatal("Decode: did not return error")
1454 }
1455 if t2.Number1 != 1 {
1456 t.Fatal("Decode: did not set Number1")
1457 }
1458}
Russ Cox09b736a2012-06-07 01:48:55 -04001459
Russ Cox7b2b8ed2014-10-07 11:07:04 -04001460// Test that a null for ,string is not replaced with the previous quoted string (issue 7046).
1461// It should also not be an error (issue 2540, issue 8587).
Emil Hessman880442f2014-01-03 10:13:28 -08001462func TestNullString(t *testing.T) {
1463 type T struct {
Russ Cox7b2b8ed2014-10-07 11:07:04 -04001464 A int `json:",string"`
1465 B int `json:",string"`
1466 C *int `json:",string"`
Emil Hessman880442f2014-01-03 10:13:28 -08001467 }
Russ Cox7b2b8ed2014-10-07 11:07:04 -04001468 data := []byte(`{"A": "1", "B": null, "C": null}`)
Emil Hessman880442f2014-01-03 10:13:28 -08001469 var s T
Russ Cox7b2b8ed2014-10-07 11:07:04 -04001470 s.B = 1
1471 s.C = new(int)
1472 *s.C = 2
Emil Hessman880442f2014-01-03 10:13:28 -08001473 err := Unmarshal(data, &s)
Russ Cox7b2b8ed2014-10-07 11:07:04 -04001474 if err != nil {
Emil Hessman2c987e12014-12-27 20:52:17 +01001475 t.Fatalf("Unmarshal: %v", err)
Russ Cox7b2b8ed2014-10-07 11:07:04 -04001476 }
1477 if s.B != 1 || s.C != nil {
1478 t.Fatalf("after Unmarshal, s.B=%d, s.C=%p, want 1, nil", s.B, s.C)
Emil Hessman880442f2014-01-03 10:13:28 -08001479 }
1480}
1481
Russ Cox09b736a2012-06-07 01:48:55 -04001482func intp(x int) *int {
1483 p := new(int)
1484 *p = x
1485 return p
1486}
1487
1488func intpp(x *int) **int {
1489 pp := new(*int)
1490 *pp = x
1491 return pp
1492}
1493
1494var interfaceSetTests = []struct {
1495 pre interface{}
1496 json string
1497 post interface{}
1498}{
1499 {"foo", `"bar"`, "bar"},
1500 {"foo", `2`, 2.0},
1501 {"foo", `true`, true},
1502 {"foo", `null`, nil},
1503
1504 {nil, `null`, nil},
1505 {new(int), `null`, nil},
1506 {(*int)(nil), `null`, nil},
1507 {new(*int), `null`, new(*int)},
1508 {(**int)(nil), `null`, nil},
1509 {intp(1), `null`, nil},
1510 {intpp(nil), `null`, intpp(nil)},
1511 {intpp(intp(1)), `null`, intpp(nil)},
1512}
1513
1514func TestInterfaceSet(t *testing.T) {
1515 for _, tt := range interfaceSetTests {
1516 b := struct{ X interface{} }{tt.pre}
1517 blob := `{"X":` + tt.json + `}`
1518 if err := Unmarshal([]byte(blob), &b); err != nil {
1519 t.Errorf("Unmarshal %#q: %v", blob, err)
1520 continue
1521 }
1522 if !reflect.DeepEqual(b.X, tt.post) {
1523 t.Errorf("Unmarshal %#q into %#v: X=%#v, want %#v", blob, tt.pre, b.X, tt.post)
1524 }
1525 }
1526}
Rick Arnoldc90739e2012-11-12 15:35:11 -05001527
Russ Coxf444b482016-10-12 16:54:02 -04001528type NullTest struct {
1529 Bool bool
1530 Int int
1531 Int8 int8
1532 Int16 int16
1533 Int32 int32
1534 Int64 int64
1535 Uint uint
1536 Uint8 uint8
1537 Uint16 uint16
1538 Uint32 uint32
1539 Uint64 uint64
1540 Float32 float32
1541 Float64 float64
1542 String string
1543 PBool *bool
1544 Map map[string]string
1545 Slice []string
1546 Interface interface{}
1547
1548 PRaw *RawMessage
1549 PTime *time.Time
1550 PBigInt *big.Int
1551 PText *MustNotUnmarshalText
1552 PBuffer *bytes.Buffer // has methods, just not relevant ones
1553 PStruct *struct{}
1554
1555 Raw RawMessage
1556 Time time.Time
1557 BigInt big.Int
1558 Text MustNotUnmarshalText
1559 Buffer bytes.Buffer
1560 Struct struct{}
1561}
1562
1563type NullTestStrings struct {
1564 Bool bool `json:",string"`
1565 Int int `json:",string"`
1566 Int8 int8 `json:",string"`
1567 Int16 int16 `json:",string"`
1568 Int32 int32 `json:",string"`
1569 Int64 int64 `json:",string"`
1570 Uint uint `json:",string"`
1571 Uint8 uint8 `json:",string"`
1572 Uint16 uint16 `json:",string"`
1573 Uint32 uint32 `json:",string"`
1574 Uint64 uint64 `json:",string"`
1575 Float32 float32 `json:",string"`
1576 Float64 float64 `json:",string"`
1577 String string `json:",string"`
1578 PBool *bool `json:",string"`
1579 Map map[string]string `json:",string"`
1580 Slice []string `json:",string"`
1581 Interface interface{} `json:",string"`
1582
1583 PRaw *RawMessage `json:",string"`
1584 PTime *time.Time `json:",string"`
1585 PBigInt *big.Int `json:",string"`
1586 PText *MustNotUnmarshalText `json:",string"`
1587 PBuffer *bytes.Buffer `json:",string"`
1588 PStruct *struct{} `json:",string"`
1589
1590 Raw RawMessage `json:",string"`
1591 Time time.Time `json:",string"`
1592 BigInt big.Int `json:",string"`
1593 Text MustNotUnmarshalText `json:",string"`
1594 Buffer bytes.Buffer `json:",string"`
1595 Struct struct{} `json:",string"`
1596}
1597
Rick Arnoldc90739e2012-11-12 15:35:11 -05001598// JSON null values should be ignored for primitives and string values instead of resulting in an error.
1599// Issue 2540
1600func TestUnmarshalNulls(t *testing.T) {
Russ Coxf444b482016-10-12 16:54:02 -04001601 // Unmarshal docs:
1602 // The JSON null value unmarshals into an interface, map, pointer, or slice
1603 // by setting that Go value to nil. Because null is often used in JSON to mean
1604 // ``not present,'' unmarshaling a JSON null into any other Go type has no effect
1605 // on the value and produces no error.
Rick Arnoldc90739e2012-11-12 15:35:11 -05001606
Russ Coxf444b482016-10-12 16:54:02 -04001607 jsonData := []byte(`{
1608 "Bool" : null,
1609 "Int" : null,
1610 "Int8" : null,
1611 "Int16" : null,
1612 "Int32" : null,
1613 "Int64" : null,
1614 "Uint" : null,
1615 "Uint8" : null,
1616 "Uint16" : null,
1617 "Uint32" : null,
1618 "Uint64" : null,
1619 "Float32" : null,
1620 "Float64" : null,
1621 "String" : null,
1622 "PBool": null,
1623 "Map": null,
1624 "Slice": null,
1625 "Interface": null,
1626 "PRaw": null,
1627 "PTime": null,
1628 "PBigInt": null,
1629 "PText": null,
1630 "PBuffer": null,
1631 "PStruct": null,
1632 "Raw": null,
1633 "Time": null,
1634 "BigInt": null,
1635 "Text": null,
1636 "Buffer": null,
1637 "Struct": null
1638 }`)
1639 nulls := NullTest{
1640 Bool: true,
1641 Int: 2,
1642 Int8: 3,
1643 Int16: 4,
1644 Int32: 5,
1645 Int64: 6,
1646 Uint: 7,
1647 Uint8: 8,
1648 Uint16: 9,
1649 Uint32: 10,
1650 Uint64: 11,
1651 Float32: 12.1,
1652 Float64: 13.1,
1653 String: "14",
1654 PBool: new(bool),
1655 Map: map[string]string{},
1656 Slice: []string{},
1657 Interface: new(MustNotUnmarshalJSON),
1658 PRaw: new(RawMessage),
1659 PTime: new(time.Time),
1660 PBigInt: new(big.Int),
1661 PText: new(MustNotUnmarshalText),
1662 PStruct: new(struct{}),
1663 PBuffer: new(bytes.Buffer),
1664 Raw: RawMessage("123"),
1665 Time: time.Unix(123456789, 0),
1666 BigInt: *big.NewInt(123),
1667 }
1668
1669 before := nulls.Time.String()
Rick Arnoldc90739e2012-11-12 15:35:11 -05001670
1671 err := Unmarshal(jsonData, &nulls)
1672 if err != nil {
1673 t.Errorf("Unmarshal of null values failed: %v", err)
1674 }
1675 if !nulls.Bool || nulls.Int != 2 || nulls.Int8 != 3 || nulls.Int16 != 4 || nulls.Int32 != 5 || nulls.Int64 != 6 ||
1676 nulls.Uint != 7 || nulls.Uint8 != 8 || nulls.Uint16 != 9 || nulls.Uint32 != 10 || nulls.Uint64 != 11 ||
1677 nulls.Float32 != 12.1 || nulls.Float64 != 13.1 || nulls.String != "14" {
Rick Arnoldc90739e2012-11-12 15:35:11 -05001678 t.Errorf("Unmarshal of null values affected primitives")
1679 }
Russ Coxf444b482016-10-12 16:54:02 -04001680
1681 if nulls.PBool != nil {
1682 t.Errorf("Unmarshal of null did not clear nulls.PBool")
1683 }
1684 if nulls.Map != nil {
1685 t.Errorf("Unmarshal of null did not clear nulls.Map")
1686 }
1687 if nulls.Slice != nil {
1688 t.Errorf("Unmarshal of null did not clear nulls.Slice")
1689 }
1690 if nulls.Interface != nil {
1691 t.Errorf("Unmarshal of null did not clear nulls.Interface")
1692 }
1693 if nulls.PRaw != nil {
1694 t.Errorf("Unmarshal of null did not clear nulls.PRaw")
1695 }
1696 if nulls.PTime != nil {
1697 t.Errorf("Unmarshal of null did not clear nulls.PTime")
1698 }
1699 if nulls.PBigInt != nil {
1700 t.Errorf("Unmarshal of null did not clear nulls.PBigInt")
1701 }
1702 if nulls.PText != nil {
1703 t.Errorf("Unmarshal of null did not clear nulls.PText")
1704 }
1705 if nulls.PBuffer != nil {
1706 t.Errorf("Unmarshal of null did not clear nulls.PBuffer")
1707 }
1708 if nulls.PStruct != nil {
1709 t.Errorf("Unmarshal of null did not clear nulls.PStruct")
1710 }
1711
1712 if string(nulls.Raw) != "null" {
1713 t.Errorf("Unmarshal of RawMessage null did not record null: %v", string(nulls.Raw))
1714 }
1715 if nulls.Time.String() != before {
1716 t.Errorf("Unmarshal of time.Time null set time to %v", nulls.Time.String())
1717 }
1718 if nulls.BigInt.String() != "123" {
1719 t.Errorf("Unmarshal of big.Int null set int to %v", nulls.BigInt.String())
1720 }
1721}
1722
1723type MustNotUnmarshalJSON struct{}
1724
1725func (x MustNotUnmarshalJSON) UnmarshalJSON(data []byte) error {
1726 return errors.New("MustNotUnmarshalJSON was used")
1727}
1728
1729type MustNotUnmarshalText struct{}
1730
1731func (x MustNotUnmarshalText) UnmarshalText(text []byte) error {
1732 return errors.New("MustNotUnmarshalText was used")
Rick Arnoldc90739e2012-11-12 15:35:11 -05001733}
Ryan Sladea4600122012-12-30 15:40:42 +11001734
1735func TestStringKind(t *testing.T) {
1736 type stringKind string
Ryan Sladea4600122012-12-30 15:40:42 +11001737
1738 var m1, m2 map[stringKind]int
1739 m1 = map[stringKind]int{
1740 "foo": 42,
1741 }
1742
1743 data, err := Marshal(m1)
1744 if err != nil {
Andrew Gerrand143f3fd2015-09-01 17:51:39 +10001745 t.Errorf("Unexpected error marshaling: %v", err)
Ryan Sladea4600122012-12-30 15:40:42 +11001746 }
1747
1748 err = Unmarshal(data, &m2)
1749 if err != nil {
Andrew Gerrand143f3fd2015-09-01 17:51:39 +10001750 t.Errorf("Unexpected error unmarshaling: %v", err)
Ryan Sladea4600122012-12-30 15:40:42 +11001751 }
1752
1753 if !reflect.DeepEqual(m1, m2) {
1754 t.Error("Items should be equal after encoding and then decoding")
1755 }
Håvard Haugen4302fd02015-04-26 23:52:42 +02001756}
Ryan Sladea4600122012-12-30 15:40:42 +11001757
Håvard Haugen4302fd02015-04-26 23:52:42 +02001758// Custom types with []byte as underlying type could not be marshalled
1759// and then unmarshalled.
1760// Issue 8962.
1761func TestByteKind(t *testing.T) {
1762 type byteKind []byte
1763
1764 a := byteKind("hello")
1765
1766 data, err := Marshal(a)
1767 if err != nil {
1768 t.Error(err)
1769 }
1770 var b byteKind
1771 err = Unmarshal(data, &b)
1772 if err != nil {
1773 t.Fatal(err)
1774 }
1775 if !reflect.DeepEqual(a, b) {
1776 t.Errorf("expected %v == %v", a, b)
1777 }
Ryan Sladea4600122012-12-30 15:40:42 +11001778}
Rémy Oudompheng406ca3c2013-01-14 08:44:16 +01001779
Håvard Haugenc60707b2015-10-25 22:42:41 +01001780// The fix for issue 8962 introduced a regression.
1781// Issue 12921.
1782func TestSliceOfCustomByte(t *testing.T) {
1783 type Uint8 uint8
1784
1785 a := []Uint8("hello")
1786
1787 data, err := Marshal(a)
1788 if err != nil {
1789 t.Fatal(err)
1790 }
1791 var b []Uint8
1792 err = Unmarshal(data, &b)
1793 if err != nil {
1794 t.Fatal(err)
1795 }
1796 if !reflect.DeepEqual(a, b) {
Dominik Honnef77f4b772016-03-22 06:37:16 +01001797 t.Fatalf("expected %v == %v", a, b)
Håvard Haugenc60707b2015-10-25 22:42:41 +01001798 }
1799}
1800
Rémy Oudompheng406ca3c2013-01-14 08:44:16 +01001801var decodeTypeErrorTests = []struct {
1802 dest interface{}
1803 src string
1804}{
1805 {new(string), `{"user": "name"}`}, // issue 4628.
1806 {new(error), `{}`}, // issue 4222
1807 {new(error), `[]`},
1808 {new(error), `""`},
1809 {new(error), `123`},
1810 {new(error), `true`},
1811}
1812
1813func TestUnmarshalTypeError(t *testing.T) {
1814 for _, item := range decodeTypeErrorTests {
1815 err := Unmarshal([]byte(item.src), item.dest)
1816 if _, ok := err.(*UnmarshalTypeError); !ok {
Russ Coxad370812013-01-29 13:34:18 -08001817 t.Errorf("expected type error for Unmarshal(%q, type %T): got %T",
Rémy Oudompheng406ca3c2013-01-14 08:44:16 +01001818 item.src, item.dest, err)
1819 }
1820 }
1821}
Rick Arnold6e3f3af2013-01-22 17:49:07 -05001822
Russ Coxad370812013-01-29 13:34:18 -08001823var unmarshalSyntaxTests = []string{
1824 "tru",
1825 "fals",
1826 "nul",
1827 "123e",
1828 `"hello`,
1829 `[1,2,3`,
1830 `{"key":1`,
1831 `{"key":1,`,
1832}
1833
1834func TestUnmarshalSyntax(t *testing.T) {
1835 var x interface{}
1836 for _, src := range unmarshalSyntaxTests {
1837 err := Unmarshal([]byte(src), &x)
1838 if _, ok := err.(*SyntaxError); !ok {
1839 t.Errorf("expected syntax error for Unmarshal(%q): got %T", src, err)
1840 }
1841 }
1842}
1843
Rick Arnold6e3f3af2013-01-22 17:49:07 -05001844// Test handling of unexported fields that should be ignored.
1845// Issue 4660
1846type unexportedFields struct {
1847 Name string
1848 m map[string]interface{} `json:"-"`
1849 m2 map[string]interface{} `json:"abcd"`
1850}
1851
1852func TestUnmarshalUnexported(t *testing.T) {
1853 input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}}`
1854 want := &unexportedFields{Name: "Bob"}
1855
1856 out := &unexportedFields{}
1857 err := Unmarshal([]byte(input), out)
1858 if err != nil {
1859 t.Errorf("got error %v, expected nil", err)
1860 }
1861 if !reflect.DeepEqual(out, want) {
1862 t.Errorf("got %q, want %q", out, want)
1863 }
1864}
Russ Coxd340a892013-02-14 14:46:15 -05001865
1866// Time3339 is a time.Time which encodes to and from JSON
1867// as an RFC 3339 time in UTC.
1868type Time3339 time.Time
1869
1870func (t *Time3339) UnmarshalJSON(b []byte) error {
1871 if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
Rob Pike707ab132013-02-25 12:43:03 -08001872 return fmt.Errorf("types: failed to unmarshal non-string value %q as an RFC 3339 time", b)
Russ Coxd340a892013-02-14 14:46:15 -05001873 }
1874 tm, err := time.Parse(time.RFC3339, string(b[1:len(b)-1]))
1875 if err != nil {
1876 return err
1877 }
1878 *t = Time3339(tm)
1879 return nil
1880}
1881
Russ Cox80e6d632015-07-30 14:05:04 +00001882func TestUnmarshalJSONLiteralError(t *testing.T) {
Russ Coxd340a892013-02-14 14:46:15 -05001883 var t3 Time3339
1884 err := Unmarshal([]byte(`"0000-00-00T00:00:00Z"`), &t3)
1885 if err == nil {
1886 t.Fatalf("expected error; got time %v", time.Time(t3))
1887 }
1888 if !strings.Contains(err.Error(), "range") {
1889 t.Errorf("got err = %v; want out of range error", err)
1890 }
1891}
Rick Arnoldcb8aebf2013-03-13 14:53:03 -04001892
1893// Test that extra object elements in an array do not result in a
1894// "data changing underfoot" error.
1895// Issue 3717
1896func TestSkipArrayObjects(t *testing.T) {
1897 json := `[{}]`
1898 var dest [0]interface{}
1899
1900 err := Unmarshal([]byte(json), &dest)
1901 if err != nil {
1902 t.Errorf("got error %q, want nil", err)
1903 }
1904}
Russ Cox5d2c3a62013-09-09 19:11:05 -04001905
1906// Test semantics of pre-filled struct fields and pre-filled map fields.
1907// Issue 4900.
1908func TestPrefilled(t *testing.T) {
1909 ptrToMap := func(m map[string]interface{}) *map[string]interface{} { return &m }
1910
1911 // Values here change, cannot reuse table across runs.
1912 var prefillTests = []struct {
1913 in string
1914 ptr interface{}
1915 out interface{}
1916 }{
1917 {
1918 in: `{"X": 1, "Y": 2}`,
1919 ptr: &XYZ{X: float32(3), Y: int16(4), Z: 1.5},
1920 out: &XYZ{X: float64(1), Y: float64(2), Z: 1.5},
1921 },
1922 {
1923 in: `{"X": 1, "Y": 2}`,
1924 ptr: ptrToMap(map[string]interface{}{"X": float32(3), "Y": int16(4), "Z": 1.5}),
1925 out: ptrToMap(map[string]interface{}{"X": float64(1), "Y": float64(2), "Z": 1.5}),
1926 },
1927 }
1928
1929 for _, tt := range prefillTests {
1930 ptrstr := fmt.Sprintf("%v", tt.ptr)
1931 err := Unmarshal([]byte(tt.in), tt.ptr) // tt.ptr edited here
1932 if err != nil {
1933 t.Errorf("Unmarshal: %v", err)
1934 }
1935 if !reflect.DeepEqual(tt.ptr, tt.out) {
1936 t.Errorf("Unmarshal(%#q, %s): have %v, want %v", tt.in, ptrstr, tt.ptr, tt.out)
1937 }
1938 }
1939}
Dave Cheney66730122014-01-02 09:49:55 +11001940
1941var invalidUnmarshalTests = []struct {
1942 v interface{}
1943 want string
1944}{
1945 {nil, "json: Unmarshal(nil)"},
1946 {struct{}{}, "json: Unmarshal(non-pointer struct {})"},
1947 {(*int)(nil), "json: Unmarshal(nil *int)"},
1948}
1949
1950func TestInvalidUnmarshal(t *testing.T) {
1951 buf := []byte(`{"a":"1"}`)
1952 for _, tt := range invalidUnmarshalTests {
1953 err := Unmarshal(buf, tt.v)
1954 if err == nil {
1955 t.Errorf("Unmarshal expecting error, got nil")
1956 continue
1957 }
1958 if got := err.Error(); got != tt.want {
1959 t.Errorf("Unmarshal = %q; want %q", got, tt.want)
1960 }
1961 }
1962}
Larz Conwell1a4e1772015-05-16 23:01:39 -04001963
Russ Cox671bddf2015-07-14 19:31:44 -04001964var invalidUnmarshalTextTests = []struct {
1965 v interface{}
1966 want string
1967}{
1968 {nil, "json: Unmarshal(nil)"},
1969 {struct{}{}, "json: Unmarshal(non-pointer struct {})"},
1970 {(*int)(nil), "json: Unmarshal(nil *int)"},
Russ Coxf444b482016-10-12 16:54:02 -04001971 {new(net.IP), "json: cannot unmarshal number into Go value of type *net.IP"},
Russ Cox671bddf2015-07-14 19:31:44 -04001972}
1973
1974func TestInvalidUnmarshalText(t *testing.T) {
1975 buf := []byte(`123`)
1976 for _, tt := range invalidUnmarshalTextTests {
1977 err := Unmarshal(buf, tt.v)
1978 if err == nil {
1979 t.Errorf("Unmarshal expecting error, got nil")
1980 continue
1981 }
1982 if got := err.Error(); got != tt.want {
1983 t.Errorf("Unmarshal = %q; want %q", got, tt.want)
1984 }
1985 }
1986}
1987
Larz Conwell1a4e1772015-05-16 23:01:39 -04001988// Test that string option is ignored for invalid types.
1989// Issue 9812.
1990func TestInvalidStringOption(t *testing.T) {
1991 num := 0
1992 item := struct {
1993 T time.Time `json:",string"`
1994 M map[string]string `json:",string"`
1995 S []string `json:",string"`
1996 A [1]string `json:",string"`
1997 I interface{} `json:",string"`
1998 P *int `json:",string"`
1999 }{M: make(map[string]string), S: make([]string, 0), I: num, P: &num}
2000
2001 data, err := Marshal(item)
2002 if err != nil {
2003 t.Fatalf("Marshal: %v", err)
2004 }
2005
2006 err = Unmarshal(data, &item)
2007 if err != nil {
2008 t.Fatalf("Unmarshal: %v", err)
2009 }
2010}