github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/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  	"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  }