1// Copyright 2011 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.
4
5package json
6
7import (
8	"bytes"
9	"math"
10	"reflect"
11	"testing"
12	"unicode"
13)
14
15type Optionals struct {
16	Sr string `json:"sr"`
17	So string `json:"so,omitempty"`
18	Sw string `json:"-"`
19
20	Ir int `json:"omitempty"` // actually named omitempty, not an option
21	Io int `json:"io,omitempty"`
22
23	Slr []string `json:"slr,random"`
24	Slo []string `json:"slo,omitempty"`
25
26	Mr map[string]interface{} `json:"mr"`
27	Mo map[string]interface{} `json:",omitempty"`
28
29	Fr float64 `json:"fr"`
30	Fo float64 `json:"fo,omitempty"`
31
32	Br bool `json:"br"`
33	Bo bool `json:"bo,omitempty"`
34
35	Ur uint `json:"ur"`
36	Uo uint `json:"uo,omitempty"`
37
38	Str struct{} `json:"str"`
39	Sto struct{} `json:"sto,omitempty"`
40}
41
42var optionalsExpected = `{
43 "sr": "",
44 "omitempty": 0,
45 "slr": null,
46 "mr": {},
47 "fr": 0,
48 "br": false,
49 "ur": 0,
50 "str": {},
51 "sto": {}
52}`
53
54func TestOmitEmpty(t *testing.T) {
55	var o Optionals
56	o.Sw = "something"
57	o.Mr = map[string]interface{}{}
58	o.Mo = map[string]interface{}{}
59
60	got, err := MarshalIndent(&o, "", " ")
61	if err != nil {
62		t.Fatal(err)
63	}
64	if got := string(got); got != optionalsExpected {
65		t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)
66	}
67}
68
69type StringTag struct {
70	BoolStr bool   `json:",string"`
71	IntStr  int64  `json:",string"`
72	StrStr  string `json:",string"`
73}
74
75var stringTagExpected = `{
76 "BoolStr": "true",
77 "IntStr": "42",
78 "StrStr": "\"xzbit\""
79}`
80
81func TestStringTag(t *testing.T) {
82	var s StringTag
83	s.BoolStr = true
84	s.IntStr = 42
85	s.StrStr = "xzbit"
86	got, err := MarshalIndent(&s, "", " ")
87	if err != nil {
88		t.Fatal(err)
89	}
90	if got := string(got); got != stringTagExpected {
91		t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected)
92	}
93
94	// Verify that it round-trips.
95	var s2 StringTag
96	err = NewDecoder(bytes.NewReader(got)).Decode(&s2)
97	if err != nil {
98		t.Fatalf("Decode: %v", err)
99	}
100	if !reflect.DeepEqual(s, s2) {
101		t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2)
102	}
103}
104
105// byte slices are special even if they're renamed types.
106type renamedByte byte
107type renamedByteSlice []byte
108type renamedRenamedByteSlice []renamedByte
109
110func TestEncodeRenamedByteSlice(t *testing.T) {
111	s := renamedByteSlice("abc")
112	result, err := Marshal(s)
113	if err != nil {
114		t.Fatal(err)
115	}
116	expect := `"YWJj"`
117	if string(result) != expect {
118		t.Errorf(" got %s want %s", result, expect)
119	}
120	r := renamedRenamedByteSlice("abc")
121	result, err = Marshal(r)
122	if err != nil {
123		t.Fatal(err)
124	}
125	if string(result) != expect {
126		t.Errorf(" got %s want %s", result, expect)
127	}
128}
129
130var unsupportedValues = []interface{}{
131	math.NaN(),
132	math.Inf(-1),
133	math.Inf(1),
134}
135
136func TestUnsupportedValues(t *testing.T) {
137	for _, v := range unsupportedValues {
138		if _, err := Marshal(v); err != nil {
139			if _, ok := err.(*UnsupportedValueError); !ok {
140				t.Errorf("for %v, got %T want UnsupportedValueError", v, err)
141			}
142		} else {
143			t.Errorf("for %v, expected error", v)
144		}
145	}
146}
147
148// Ref has Marshaler and Unmarshaler methods with pointer receiver.
149type Ref int
150
151func (*Ref) MarshalJSON() ([]byte, error) {
152	return []byte(`"ref"`), nil
153}
154
155func (r *Ref) UnmarshalJSON([]byte) error {
156	*r = 12
157	return nil
158}
159
160// Val has Marshaler methods with value receiver.
161type Val int
162
163func (Val) MarshalJSON() ([]byte, error) {
164	return []byte(`"val"`), nil
165}
166
167// RefText has Marshaler and Unmarshaler methods with pointer receiver.
168type RefText int
169
170func (*RefText) MarshalText() ([]byte, error) {
171	return []byte(`"ref"`), nil
172}
173
174func (r *RefText) UnmarshalText([]byte) error {
175	*r = 13
176	return nil
177}
178
179// ValText has Marshaler methods with value receiver.
180type ValText int
181
182func (ValText) MarshalText() ([]byte, error) {
183	return []byte(`"val"`), nil
184}
185
186func TestRefValMarshal(t *testing.T) {
187	var s = struct {
188		R0 Ref
189		R1 *Ref
190		R2 RefText
191		R3 *RefText
192		V0 Val
193		V1 *Val
194		V2 ValText
195		V3 *ValText
196	}{
197		R0: 12,
198		R1: new(Ref),
199		R2: 14,
200		R3: new(RefText),
201		V0: 13,
202		V1: new(Val),
203		V2: 15,
204		V3: new(ValText),
205	}
206	const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`
207	b, err := Marshal(&s)
208	if err != nil {
209		t.Fatalf("Marshal: %v", err)
210	}
211	if got := string(b); got != want {
212		t.Errorf("got %q, want %q", got, want)
213	}
214}
215
216// C implements Marshaler and returns unescaped JSON.
217type C int
218
219func (C) MarshalJSON() ([]byte, error) {
220	return []byte(`"<&>"`), nil
221}
222
223// CText implements Marshaler and returns unescaped text.
224type CText int
225
226func (CText) MarshalText() ([]byte, error) {
227	return []byte(`"<&>"`), nil
228}
229
230func TestMarshalerEscaping(t *testing.T) {
231	var c C
232	want := `"\u003c\u0026\u003e"`
233	b, err := Marshal(c)
234	if err != nil {
235		t.Fatalf("Marshal(c): %v", err)
236	}
237	if got := string(b); got != want {
238		t.Errorf("Marshal(c) = %#q, want %#q", got, want)
239	}
240
241	var ct CText
242	want = `"\"\u003c\u0026\u003e\""`
243	b, err = Marshal(ct)
244	if err != nil {
245		t.Fatalf("Marshal(ct): %v", err)
246	}
247	if got := string(b); got != want {
248		t.Errorf("Marshal(ct) = %#q, want %#q", got, want)
249	}
250}
251
252type IntType int
253
254type MyStruct struct {
255	IntType
256}
257
258func TestAnonymousNonstruct(t *testing.T) {
259	var i IntType = 11
260	a := MyStruct{i}
261	const want = `{"IntType":11}`
262
263	b, err := Marshal(a)
264	if err != nil {
265		t.Fatalf("Marshal: %v", err)
266	}
267	if got := string(b); got != want {
268		t.Errorf("got %q, want %q", got, want)
269	}
270}
271
272type BugA struct {
273	S string
274}
275
276type BugB struct {
277	BugA
278	S string
279}
280
281type BugC struct {
282	S string
283}
284
285// Legal Go: We never use the repeated embedded field (S).
286type BugX struct {
287	A int
288	BugA
289	BugB
290}
291
292// Issue 5245.
293func TestEmbeddedBug(t *testing.T) {
294	v := BugB{
295		BugA{"A"},
296		"B",
297	}
298	b, err := Marshal(v)
299	if err != nil {
300		t.Fatal("Marshal:", err)
301	}
302	want := `{"S":"B"}`
303	got := string(b)
304	if got != want {
305		t.Fatalf("Marshal: got %s want %s", got, want)
306	}
307	// Now check that the duplicate field, S, does not appear.
308	x := BugX{
309		A: 23,
310	}
311	b, err = Marshal(x)
312	if err != nil {
313		t.Fatal("Marshal:", err)
314	}
315	want = `{"A":23}`
316	got = string(b)
317	if got != want {
318		t.Fatalf("Marshal: got %s want %s", got, want)
319	}
320}
321
322type BugD struct { // Same as BugA after tagging.
323	XXX string `json:"S"`
324}
325
326// BugD's tagged S field should dominate BugA's.
327type BugY struct {
328	BugA
329	BugD
330}
331
332// Test that a field with a tag dominates untagged fields.
333func TestTaggedFieldDominates(t *testing.T) {
334	v := BugY{
335		BugA{"BugA"},
336		BugD{"BugD"},
337	}
338	b, err := Marshal(v)
339	if err != nil {
340		t.Fatal("Marshal:", err)
341	}
342	want := `{"S":"BugD"}`
343	got := string(b)
344	if got != want {
345		t.Fatalf("Marshal: got %s want %s", got, want)
346	}
347}
348
349// There are no tags here, so S should not appear.
350type BugZ struct {
351	BugA
352	BugC
353	BugY // Contains a tagged S field through BugD; should not dominate.
354}
355
356func TestDuplicatedFieldDisappears(t *testing.T) {
357	v := BugZ{
358		BugA{"BugA"},
359		BugC{"BugC"},
360		BugY{
361			BugA{"nested BugA"},
362			BugD{"nested BugD"},
363		},
364	}
365	b, err := Marshal(v)
366	if err != nil {
367		t.Fatal("Marshal:", err)
368	}
369	want := `{}`
370	got := string(b)
371	if got != want {
372		t.Fatalf("Marshal: got %s want %s", got, want)
373	}
374}
375
376func TestStringBytes(t *testing.T) {
377	// Test that encodeState.stringBytes and encodeState.string use the same encoding.
378	es := &encodeState{}
379	var r []rune
380	for i := '\u0000'; i <= unicode.MaxRune; i++ {
381		r = append(r, i)
382	}
383	s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too
384	es.string(s)
385
386	esBytes := &encodeState{}
387	esBytes.stringBytes([]byte(s))
388
389	enc := es.Buffer.String()
390	encBytes := esBytes.Buffer.String()
391	if enc != encBytes {
392		i := 0
393		for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] {
394			i++
395		}
396		enc = enc[i:]
397		encBytes = encBytes[i:]
398		i = 0
399		for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] {
400			i++
401		}
402		enc = enc[:len(enc)-i]
403		encBytes = encBytes[:len(encBytes)-i]
404
405		if len(enc) > 20 {
406			enc = enc[:20] + "..."
407		}
408		if len(encBytes) > 20 {
409			encBytes = encBytes[:20] + "..."
410		}
411
412		t.Errorf("encodings differ at %#q vs %#q", enc, encBytes)
413	}
414}
415
416func TestIssue6458(t *testing.T) {
417	type Foo struct {
418		M RawMessage
419	}
420	x := Foo{RawMessage(`"foo"`)}
421
422	b, err := Marshal(&x)
423	if err != nil {
424		t.Fatal(err)
425	}
426	if want := `{"M":"foo"}`; string(b) != want {
427		t.Errorf("Marshal(&x) = %#q; want %#q", b, want)
428	}
429
430	b, err = Marshal(x)
431	if err != nil {
432		t.Fatal(err)
433	}
434
435	if want := `{"M":"ImZvbyI="}`; string(b) != want {
436		t.Errorf("Marshal(x) = %#q; want %#q", b, want)
437	}
438}
439
440func TestIssue10281(t *testing.T) {
441	type Foo struct {
442		N Number
443	}
444	x := Foo{Number(`invalid`)}
445
446	b, err := Marshal(&x)
447	if err == nil {
448		t.Errorf("Marshal(&x) = %#q; want error", b)
449	}
450}
451
452func TestHTMLEscape(t *testing.T) {
453	var b, want bytes.Buffer
454	m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}`
455	want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`))
456	HTMLEscape(&b, []byte(m))
457	if !bytes.Equal(b.Bytes(), want.Bytes()) {
458		t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes())
459	}
460}
461
462// golang.org/issue/8582
463func TestEncodePointerString(t *testing.T) {
464	type stringPointer struct {
465		N *int64 `json:"n,string"`
466	}
467	var n int64 = 42
468	b, err := Marshal(stringPointer{N: &n})
469	if err != nil {
470		t.Fatalf("Marshal: %v", err)
471	}
472	if got, want := string(b), `{"n":"42"}`; got != want {
473		t.Errorf("Marshal = %s, want %s", got, want)
474	}
475	var back stringPointer
476	err = Unmarshal(b, &back)
477	if err != nil {
478		t.Fatalf("Unmarshal: %v", err)
479	}
480	if back.N == nil {
481		t.Fatalf("Unmarshalled nil N field")
482	}
483	if *back.N != 42 {
484		t.Fatalf("*N = %d; want 42", *back.N)
485	}
486}
487
488var encodeStringTests = []struct {
489	in  string
490	out string
491}{
492	{"\x00", `"\u0000"`},
493	{"\x01", `"\u0001"`},
494	{"\x02", `"\u0002"`},
495	{"\x03", `"\u0003"`},
496	{"\x04", `"\u0004"`},
497	{"\x05", `"\u0005"`},
498	{"\x06", `"\u0006"`},
499	{"\x07", `"\u0007"`},
500	{"\x08", `"\u0008"`},
501	{"\x09", `"\t"`},
502	{"\x0a", `"\n"`},
503	{"\x0b", `"\u000b"`},
504	{"\x0c", `"\u000c"`},
505	{"\x0d", `"\r"`},
506	{"\x0e", `"\u000e"`},
507	{"\x0f", `"\u000f"`},
508	{"\x10", `"\u0010"`},
509	{"\x11", `"\u0011"`},
510	{"\x12", `"\u0012"`},
511	{"\x13", `"\u0013"`},
512	{"\x14", `"\u0014"`},
513	{"\x15", `"\u0015"`},
514	{"\x16", `"\u0016"`},
515	{"\x17", `"\u0017"`},
516	{"\x18", `"\u0018"`},
517	{"\x19", `"\u0019"`},
518	{"\x1a", `"\u001a"`},
519	{"\x1b", `"\u001b"`},
520	{"\x1c", `"\u001c"`},
521	{"\x1d", `"\u001d"`},
522	{"\x1e", `"\u001e"`},
523	{"\x1f", `"\u001f"`},
524}
525
526func TestEncodeString(t *testing.T) {
527	for _, tt := range encodeStringTests {
528		b, err := Marshal(tt.in)
529		if err != nil {
530			t.Errorf("Marshal(%q): %v", tt.in, err)
531			continue
532		}
533		out := string(b)
534		if out != tt.out {
535			t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out)
536		}
537	}
538}
539