Home | History | Annotate | Download | only in json
      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 
      5 package json
      6 
      7 import (
      8 	"bytes"
      9 	"math"
     10 	"reflect"
     11 	"testing"
     12 	"unicode"
     13 )
     14 
     15 type 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 
     42 var 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 
     54 func 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 
     69 type StringTag struct {
     70 	BoolStr bool   `json:",string"`
     71 	IntStr  int64  `json:",string"`
     72 	StrStr  string `json:",string"`
     73 }
     74 
     75 var stringTagExpected = `{
     76  "BoolStr": "true",
     77  "IntStr": "42",
     78  "StrStr": "\"xzbit\""
     79 }`
     80 
     81 func 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.
    106 type renamedByte byte
    107 type renamedByteSlice []byte
    108 type renamedRenamedByteSlice []renamedByte
    109 
    110 func 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 
    130 var unsupportedValues = []interface{}{
    131 	math.NaN(),
    132 	math.Inf(-1),
    133 	math.Inf(1),
    134 }
    135 
    136 func 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.
    149 type Ref int
    150 
    151 func (*Ref) MarshalJSON() ([]byte, error) {
    152 	return []byte(`"ref"`), nil
    153 }
    154 
    155 func (r *Ref) UnmarshalJSON([]byte) error {
    156 	*r = 12
    157 	return nil
    158 }
    159 
    160 // Val has Marshaler methods with value receiver.
    161 type Val int
    162 
    163 func (Val) MarshalJSON() ([]byte, error) {
    164 	return []byte(`"val"`), nil
    165 }
    166 
    167 // RefText has Marshaler and Unmarshaler methods with pointer receiver.
    168 type RefText int
    169 
    170 func (*RefText) MarshalText() ([]byte, error) {
    171 	return []byte(`"ref"`), nil
    172 }
    173 
    174 func (r *RefText) UnmarshalText([]byte) error {
    175 	*r = 13
    176 	return nil
    177 }
    178 
    179 // ValText has Marshaler methods with value receiver.
    180 type ValText int
    181 
    182 func (ValText) MarshalText() ([]byte, error) {
    183 	return []byte(`"val"`), nil
    184 }
    185 
    186 func 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.
    217 type C int
    218 
    219 func (C) MarshalJSON() ([]byte, error) {
    220 	return []byte(`"<&>"`), nil
    221 }
    222 
    223 // CText implements Marshaler and returns unescaped text.
    224 type CText int
    225 
    226 func (CText) MarshalText() ([]byte, error) {
    227 	return []byte(`"<&>"`), nil
    228 }
    229 
    230 func 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 
    252 type IntType int
    253 
    254 type MyStruct struct {
    255 	IntType
    256 }
    257 
    258 func 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 
    272 type BugA struct {
    273 	S string
    274 }
    275 
    276 type BugB struct {
    277 	BugA
    278 	S string
    279 }
    280 
    281 type BugC struct {
    282 	S string
    283 }
    284 
    285 // Legal Go: We never use the repeated embedded field (S).
    286 type BugX struct {
    287 	A int
    288 	BugA
    289 	BugB
    290 }
    291 
    292 // Issue 5245.
    293 func 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 
    322 type BugD struct { // Same as BugA after tagging.
    323 	XXX string `json:"S"`
    324 }
    325 
    326 // BugD's tagged S field should dominate BugA's.
    327 type BugY struct {
    328 	BugA
    329 	BugD
    330 }
    331 
    332 // Test that a field with a tag dominates untagged fields.
    333 func 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.
    350 type BugZ struct {
    351 	BugA
    352 	BugC
    353 	BugY // Contains a tagged S field through BugD; should not dominate.
    354 }
    355 
    356 func 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 
    376 func 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 	_, err := es.string(s)
    385 	if err != nil {
    386 		t.Fatal(err)
    387 	}
    388 
    389 	esBytes := &encodeState{}
    390 	_, err = esBytes.stringBytes([]byte(s))
    391 	if err != nil {
    392 		t.Fatal(err)
    393 	}
    394 
    395 	enc := es.Buffer.String()
    396 	encBytes := esBytes.Buffer.String()
    397 	if enc != encBytes {
    398 		i := 0
    399 		for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] {
    400 			i++
    401 		}
    402 		enc = enc[i:]
    403 		encBytes = encBytes[i:]
    404 		i = 0
    405 		for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] {
    406 			i++
    407 		}
    408 		enc = enc[:len(enc)-i]
    409 		encBytes = encBytes[:len(encBytes)-i]
    410 
    411 		if len(enc) > 20 {
    412 			enc = enc[:20] + "..."
    413 		}
    414 		if len(encBytes) > 20 {
    415 			encBytes = encBytes[:20] + "..."
    416 		}
    417 
    418 		t.Errorf("encodings differ at %#q vs %#q", enc, encBytes)
    419 	}
    420 }
    421 
    422 func TestIssue6458(t *testing.T) {
    423 	type Foo struct {
    424 		M RawMessage
    425 	}
    426 	x := Foo{RawMessage(`"foo"`)}
    427 
    428 	b, err := Marshal(&x)
    429 	if err != nil {
    430 		t.Fatal(err)
    431 	}
    432 	if want := `{"M":"foo"}`; string(b) != want {
    433 		t.Errorf("Marshal(&x) = %#q; want %#q", b, want)
    434 	}
    435 
    436 	b, err = Marshal(x)
    437 	if err != nil {
    438 		t.Fatal(err)
    439 	}
    440 
    441 	if want := `{"M":"ImZvbyI="}`; string(b) != want {
    442 		t.Errorf("Marshal(x) = %#q; want %#q", b, want)
    443 	}
    444 }
    445 
    446 func TestHTMLEscape(t *testing.T) {
    447 	var b, want bytes.Buffer
    448 	m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}`
    449 	want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`))
    450 	HTMLEscape(&b, []byte(m))
    451 	if !bytes.Equal(b.Bytes(), want.Bytes()) {
    452 		t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes())
    453 	}
    454 }
    455 
    456 // golang.org/issue/8582
    457 func TestEncodePointerString(t *testing.T) {
    458 	type stringPointer struct {
    459 		N *int64 `json:"n,string"`
    460 	}
    461 	var n int64 = 42
    462 	b, err := Marshal(stringPointer{N: &n})
    463 	if err != nil {
    464 		t.Fatalf("Marshal: %v", err)
    465 	}
    466 	if got, want := string(b), `{"n":"42"}`; got != want {
    467 		t.Errorf("Marshal = %s, want %s", got, want)
    468 	}
    469 	var back stringPointer
    470 	err = Unmarshal(b, &back)
    471 	if err != nil {
    472 		t.Fatalf("Unmarshal: %v", err)
    473 	}
    474 	if back.N == nil {
    475 		t.Fatalf("Unmarshalled nil N field")
    476 	}
    477 	if *back.N != 42 {
    478 		t.Fatalf("*N = %d; want 42", *back.N)
    479 	}
    480 }
    481 
    482 var encodeStringTests = []struct {
    483 	in  string
    484 	out string
    485 }{
    486 	{"\x00", `"\u0000"`},
    487 	{"\x01", `"\u0001"`},
    488 	{"\x02", `"\u0002"`},
    489 	{"\x03", `"\u0003"`},
    490 	{"\x04", `"\u0004"`},
    491 	{"\x05", `"\u0005"`},
    492 	{"\x06", `"\u0006"`},
    493 	{"\x07", `"\u0007"`},
    494 	{"\x08", `"\u0008"`},
    495 	{"\x09", `"\t"`},
    496 	{"\x0a", `"\n"`},
    497 	{"\x0b", `"\u000b"`},
    498 	{"\x0c", `"\u000c"`},
    499 	{"\x0d", `"\r"`},
    500 	{"\x0e", `"\u000e"`},
    501 	{"\x0f", `"\u000f"`},
    502 	{"\x10", `"\u0010"`},
    503 	{"\x11", `"\u0011"`},
    504 	{"\x12", `"\u0012"`},
    505 	{"\x13", `"\u0013"`},
    506 	{"\x14", `"\u0014"`},
    507 	{"\x15", `"\u0015"`},
    508 	{"\x16", `"\u0016"`},
    509 	{"\x17", `"\u0017"`},
    510 	{"\x18", `"\u0018"`},
    511 	{"\x19", `"\u0019"`},
    512 	{"\x1a", `"\u001a"`},
    513 	{"\x1b", `"\u001b"`},
    514 	{"\x1c", `"\u001c"`},
    515 	{"\x1d", `"\u001d"`},
    516 	{"\x1e", `"\u001e"`},
    517 	{"\x1f", `"\u001f"`},
    518 }
    519 
    520 func TestEncodeString(t *testing.T) {
    521 	for _, tt := range encodeStringTests {
    522 		b, err := Marshal(tt.in)
    523 		if err != nil {
    524 			t.Errorf("Marshal(%q): %v", tt.in, err)
    525 			continue
    526 		}
    527 		out := string(b)
    528 		if out != tt.out {
    529 			t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out)
    530 		}
    531 	}
    532 }
    533