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.
24 var txType = reflect.TypeOf((*tx)(nil)).Elem()
26 // A type that can unmarshal itself.
28 type unmarshaler struct {
32 func (u *unmarshaler) UnmarshalJSON(b []byte) os.Error {
33 *u = unmarshaler{true} // All we need to see that UnmarshalJson is called.
42 um0, um1 unmarshaler // target2 of unmarshaling
44 umtrue = unmarshaler{true}
45 umslice = []unmarshaler{unmarshaler{true}}
46 umslicep = new([]unmarshaler)
47 umstruct = ustruct{unmarshaler{true}}
50 type unmarshalTest struct {
57 var unmarshalTests = []unmarshalTest{
59 {`true`, new(bool), true, nil},
60 {`1`, new(int), 1, nil},
61 {`1.2`, new(float64), 1.2, nil},
62 {`-5`, new(int16), int16(-5), nil},
63 {`"a\u1234"`, new(string), "a\u1234", nil},
64 {`"http:\/\/"`, new(string), "http://", nil},
65 {`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E", nil},
66 {`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil},
67 {"null", new(interface{}), nil, nil},
68 {`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.TypeOf("")}},
69 {`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
72 {`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}},
75 {allValueIndent, new(All), allValue, nil},
76 {allValueCompact, new(All), allValue, nil},
77 {allValueIndent, new(*All), &allValue, nil},
78 {allValueCompact, new(*All), &allValue, nil},
79 {pallValueIndent, new(All), pallValue, nil},
80 {pallValueCompact, new(All), pallValue, nil},
81 {pallValueIndent, new(*All), &pallValue, nil},
82 {pallValueCompact, new(*All), &pallValue, nil},
84 // unmarshal interface test
85 {`{"T":false}`, &um0, umtrue, nil}, // use "false" so test will fail if custom unmarshaler is not called
86 {`{"T":false}`, &ump, &umtrue, nil},
87 {`[{"T":false}]`, &umslice, umslice, nil},
88 {`[{"T":false}]`, &umslicep, &umslice, nil},
89 {`{"M":{"T":false}}`, &umstruct, umstruct, nil},
92 func TestMarshal(t *testing.T) {
93 b, err := Marshal(allValue)
95 t.Fatalf("Marshal allValue: %v", err)
97 if string(b) != allValueCompact {
98 t.Errorf("Marshal allValueCompact")
99 diff(t, b, []byte(allValueCompact))
103 b, err = Marshal(pallValue)
105 t.Fatalf("Marshal pallValue: %v", err)
107 if string(b) != pallValueCompact {
108 t.Errorf("Marshal pallValueCompact")
109 diff(t, b, []byte(pallValueCompact))
114 func TestMarshalBadUTF8(t *testing.T) {
115 s := "hello\xffworld"
118 t.Fatal("Marshal bad UTF8: no error")
121 t.Fatal("Marshal returned data")
123 if _, ok := err.(*InvalidUTF8Error); !ok {
124 t.Fatalf("Marshal did not return InvalidUTF8Error: %T %v", err, err)
128 func TestUnmarshal(t *testing.T) {
129 for i, tt := range unmarshalTests {
132 if err := checkValid(in, &scan); err != nil {
133 if !reflect.DeepEqual(err, tt.err) {
134 t.Errorf("#%d: checkValid: %#v", i, err)
141 // v = new(right-type)
142 v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
143 if err := Unmarshal([]byte(in), v.Interface()); !reflect.DeepEqual(err, tt.err) {
144 t.Errorf("#%d: %v want %v", i, err, tt.err)
147 if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
148 t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
149 data, _ := Marshal(v.Elem().Interface())
150 println(string(data))
151 data, _ = Marshal(tt.out)
152 println(string(data))
158 func TestUnmarshalMarshal(t *testing.T) {
161 if err := Unmarshal(jsonBig, &v); err != nil {
162 t.Fatalf("Unmarshal: %v", err)
166 t.Fatalf("Marshal: %v", err)
168 if bytes.Compare(jsonBig, b) != 0 {
169 t.Errorf("Marshal jsonBig")
175 func TestLargeByteSlice(t *testing.T) {
176 s0 := make([]byte, 2000)
180 b, err := Marshal(s0)
182 t.Fatalf("Marshal: %v", err)
185 if err := Unmarshal(b, &s1); err != nil {
186 t.Fatalf("Unmarshal: %v", err)
188 if bytes.Compare(s0, s1) != 0 {
189 t.Errorf("Marshal large byte slice")
198 func TestUnmarshalInterface(t *testing.T) {
200 var i interface{} = &xint
201 if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil {
202 t.Fatalf("Unmarshal: %v", err)
205 t.Fatalf("Did not write to xint")
209 func TestUnmarshalPtrPtr(t *testing.T) {
212 if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil {
213 t.Fatalf("Unmarshal: %v", err)
216 t.Fatalf("Did not write to xint")
220 func TestEscape(t *testing.T) {
221 const input = `"foobar"<html>`
222 const expected = `"\"foobar\"\u003chtml\u003e"`
223 b, err := Marshal(input)
225 t.Fatalf("Marshal error: %v", err)
227 if s := string(b); s != expected {
228 t.Errorf("Encoding of [%s] was [%s], want [%s]", input, s, expected)
232 func TestHTMLEscape(t *testing.T) {
233 b, err := MarshalForHTML("foobarbaz<>&quux")
235 t.Fatalf("MarshalForHTML error: %v", err)
237 if !bytes.Equal(b, []byte(`"foobarbaz\u003c\u003e\u0026quux"`)) {
238 t.Fatalf("Unexpected encoding of \"<>&\": %s", b)
242 func noSpace(c int) int {
265 Foo string `json:"bar"`
286 MapP map[string]*Small
287 PMap *map[string]Small
288 PMapP *map[string]*Small
290 EmptyMap map[string]Small
291 NilMap map[string]Small
308 Interface interface{}
309 PInterface *interface{}
335 Map: map[string]Small{
336 "17": {Tag: "tag17"},
337 "18": {Tag: "tag18"},
339 MapP: map[string]*Small{
340 "19": &Small{Tag: "tag19"},
343 EmptyMap: map[string]Small{},
344 Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}},
345 SliceP: []*Small{&Small{Tag: "tag22"}, nil, &Small{Tag: "tag23"}},
346 EmptySlice: []Small{},
347 StringSlice: []string{"str24", "str25", "str26"},
348 ByteSlice: []byte{27, 28, 29},
349 Small: Small{Tag: "tag30"},
350 PSmall: &Small{Tag: "tag31"},
355 PBool: &allValue.Bool,
357 PInt8: &allValue.Int8,
358 PInt16: &allValue.Int16,
359 PInt32: &allValue.Int32,
360 PInt64: &allValue.Int64,
361 PUint: &allValue.Uint,
362 PUint8: &allValue.Uint8,
363 PUint16: &allValue.Uint16,
364 PUint32: &allValue.Uint32,
365 PUint64: &allValue.Uint64,
366 PUintptr: &allValue.Uintptr,
367 PFloat32: &allValue.Float32,
368 PFloat64: &allValue.Float64,
369 PString: &allValue.String,
371 PMapP: &allValue.MapP,
372 PSlice: &allValue.Slice,
373 PSliceP: &allValue.SliceP,
374 PPSmall: &allValue.PSmall,
375 PInterface: &allValue.Interface,
378 var allValueIndent = `{
466 var allValueCompact = strings.Map(noSpace, allValueIndent)
468 var pallValueIndent = `{
552 var pallValueCompact = strings.Map(noSpace, pallValueIndent)