github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/encoding/json/encode_test.go (about)

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