1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
25 var txType = reflect.TypeOf((*tx)(nil)).Elem()
27 // A type that can unmarshal itself.
29 type unmarshaler struct {
33 func (u *unmarshaler) UnmarshalJSON(b []byte) error {
34 *u = unmarshaler{true} // All we need to see that UnmarshalJson is called.
43 um0, um1 unmarshaler // target2 of unmarshaling
45 umtrue = unmarshaler{true}
46 umslice = []unmarshaler{{true}}
47 umslicep = new([]unmarshaler)
48 umstruct = ustruct{unmarshaler{true}}
51 type unmarshalTest struct {
58 var unmarshalTests = []unmarshalTest{
60 {`true`, new(bool), true, nil},
61 {`1`, new(int), 1, nil},
62 {`1.2`, new(float64), 1.2, nil},
63 {`-5`, new(int16), int16(-5), nil},
64 {`"a\u1234"`, new(string), "a\u1234", nil},
65 {`"http:\/\/"`, new(string), "http://", nil},
66 {`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E", nil},
67 {`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil},
68 {"null", new(interface{}), nil, nil},
69 {`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.TypeOf("")}},
70 {`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
73 {`{"Y": 1, "Z": 2}`, new(T), T{Y: 1}, nil},
76 {`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}},
77 {`[1, 2, 3+]`, nil, nil, &SyntaxError{"invalid character '+' after array element", 9}},
80 {`[1, 2, 3]`, new([3]int), [3]int{1, 2, 3}, nil},
81 {`[1, 2, 3]`, new([1]int), [1]int{1}, nil},
82 {`[1, 2, 3]`, new([5]int), [5]int{1, 2, 3, 0, 0}, nil},
85 {allValueIndent, new(All), allValue, nil},
86 {allValueCompact, new(All), allValue, nil},
87 {allValueIndent, new(*All), &allValue, nil},
88 {allValueCompact, new(*All), &allValue, nil},
89 {pallValueIndent, new(All), pallValue, nil},
90 {pallValueCompact, new(All), pallValue, nil},
91 {pallValueIndent, new(*All), &pallValue, nil},
92 {pallValueCompact, new(*All), &pallValue, nil},
94 // unmarshal interface test
95 {`{"T":false}`, &um0, umtrue, nil}, // use "false" so test will fail if custom unmarshaler is not called
96 {`{"T":false}`, &ump, &umtrue, nil},
97 {`[{"T":false}]`, &umslice, umslice, nil},
98 {`[{"T":false}]`, &umslicep, &umslice, nil},
99 {`{"M":{"T":false}}`, &umstruct, umstruct, nil},
102 func TestMarshal(t *testing.T) {
103 b, err := Marshal(allValue)
105 t.Fatalf("Marshal allValue: %v", err)
107 if string(b) != allValueCompact {
108 t.Errorf("Marshal allValueCompact")
109 diff(t, b, []byte(allValueCompact))
113 b, err = Marshal(pallValue)
115 t.Fatalf("Marshal pallValue: %v", err)
117 if string(b) != pallValueCompact {
118 t.Errorf("Marshal pallValueCompact")
119 diff(t, b, []byte(pallValueCompact))
124 func TestMarshalBadUTF8(t *testing.T) {
125 s := "hello\xffworld"
128 t.Fatal("Marshal bad UTF8: no error")
131 t.Fatal("Marshal returned data")
133 if _, ok := err.(*InvalidUTF8Error); !ok {
134 t.Fatalf("Marshal did not return InvalidUTF8Error: %T %v", err, err)
138 func TestUnmarshal(t *testing.T) {
139 for i, tt := range unmarshalTests {
142 if err := checkValid(in, &scan); err != nil {
143 if !reflect.DeepEqual(err, tt.err) {
144 t.Errorf("#%d: checkValid: %#v", i, err)
151 // v = new(right-type)
152 v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
153 if err := Unmarshal([]byte(in), v.Interface()); !reflect.DeepEqual(err, tt.err) {
154 t.Errorf("#%d: %v want %v", i, err, tt.err)
157 if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
158 t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
159 data, _ := Marshal(v.Elem().Interface())
160 println(string(data))
161 data, _ = Marshal(tt.out)
162 println(string(data))
168 func TestUnmarshalMarshal(t *testing.T) {
171 if err := Unmarshal(jsonBig, &v); err != nil {
172 t.Fatalf("Unmarshal: %v", err)
176 t.Fatalf("Marshal: %v", err)
178 if bytes.Compare(jsonBig, b) != 0 {
179 t.Errorf("Marshal jsonBig")
185 func TestLargeByteSlice(t *testing.T) {
186 s0 := make([]byte, 2000)
190 b, err := Marshal(s0)
192 t.Fatalf("Marshal: %v", err)
195 if err := Unmarshal(b, &s1); err != nil {
196 t.Fatalf("Unmarshal: %v", err)
198 if bytes.Compare(s0, s1) != 0 {
199 t.Errorf("Marshal large byte slice")
208 func TestUnmarshalInterface(t *testing.T) {
210 var i interface{} = &xint
211 if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil {
212 t.Fatalf("Unmarshal: %v", err)
215 t.Fatalf("Did not write to xint")
219 func TestUnmarshalPtrPtr(t *testing.T) {
222 if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil {
223 t.Fatalf("Unmarshal: %v", err)
226 t.Fatalf("Did not write to xint")
230 func TestEscape(t *testing.T) {
231 const input = `"foobar"<html>`
232 const expected = `"\"foobar\"\u003chtml\u003e"`
233 b, err := Marshal(input)
235 t.Fatalf("Marshal error: %v", err)
237 if s := string(b); s != expected {
238 t.Errorf("Encoding of [%s] was [%s], want [%s]", input, s, expected)
242 func TestHTMLEscape(t *testing.T) {
243 b, err := MarshalForHTML("foobarbaz<>&quux")
245 t.Fatalf("MarshalForHTML error: %v", err)
247 if !bytes.Equal(b, []byte(`"foobarbaz\u003c\u003e\u0026quux"`)) {
248 t.Fatalf("Unexpected encoding of \"<>&\": %s", b)
252 // WrongString is a struct that's misusing the ,string modifier.
253 type WrongString struct {
254 Message string `json:"result,string"`
257 type wrongStringTest struct {
261 // TODO(bradfitz): as part of Issue 2331, fix these tests' expected
262 // error values to be helpful, rather than the confusing messages they
264 var wrongStringTests = []wrongStringTest{
265 {`{"result":"x"}`, "JSON decoder out of sync - data changing underfoot?"},
266 {`{"result":"foo"}`, "json: cannot unmarshal bool into Go value of type string"},
267 {`{"result":"123"}`, "json: cannot unmarshal number into Go value of type string"},
270 // If people misuse the ,string modifier, the error message should be
271 // helpful, telling the user that they're doing it wrong.
272 func TestErrorMessageFromMisusedString(t *testing.T) {
273 for n, tt := range wrongStringTests {
274 r := strings.NewReader(tt.in)
276 err := NewDecoder(r).Decode(&s)
277 got := fmt.Sprintf("%v", err)
279 t.Errorf("%d. got err = %q, want %q", n, got, tt.err)
284 func noSpace(c rune) rune {
307 Foo string `json:"bar"`
308 Foo2 string `json:"bar2,dummyopt"`
310 IntStr int64 `json:",string"`
331 MapP map[string]*Small
332 PMap *map[string]Small
333 PMapP *map[string]*Small
335 EmptyMap map[string]Small
336 NilMap map[string]Small
353 Interface interface{}
354 PInterface *interface{}
382 Map: map[string]Small{
383 "17": {Tag: "tag17"},
384 "18": {Tag: "tag18"},
386 MapP: map[string]*Small{
387 "19": {Tag: "tag19"},
390 EmptyMap: map[string]Small{},
391 Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}},
392 SliceP: []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}},
393 EmptySlice: []Small{},
394 StringSlice: []string{"str24", "str25", "str26"},
395 ByteSlice: []byte{27, 28, 29},
396 Small: Small{Tag: "tag30"},
397 PSmall: &Small{Tag: "tag31"},
402 PBool: &allValue.Bool,
404 PInt8: &allValue.Int8,
405 PInt16: &allValue.Int16,
406 PInt32: &allValue.Int32,
407 PInt64: &allValue.Int64,
408 PUint: &allValue.Uint,
409 PUint8: &allValue.Uint8,
410 PUint16: &allValue.Uint16,
411 PUint32: &allValue.Uint32,
412 PUint64: &allValue.Uint64,
413 PUintptr: &allValue.Uintptr,
414 PFloat32: &allValue.Float32,
415 PFloat64: &allValue.Float64,
416 PString: &allValue.String,
418 PMapP: &allValue.MapP,
419 PSlice: &allValue.Slice,
420 PSliceP: &allValue.SliceP,
421 PPSmall: &allValue.PSmall,
422 PInterface: &allValue.Interface,
425 var allValueIndent = `{
515 var allValueCompact = strings.Map(noSpace, allValueIndent)
517 var pallValueIndent = `{
603 var pallValueCompact = strings.Map(noSpace, pallValueIndent)