github.com/qiniu/dyn@v1.3.0/text/internal/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  )
    13  
    14  type Optionals struct {
    15  	Sr string `json:"sr"`
    16  	So string `json:"so,omitempty"`
    17  	Sw string `json:"-"`
    18  
    19  	Ir int `json:"omitempty"` // actually named omitempty, not an option
    20  	Io int `json:"io,omitempty"`
    21  
    22  	Slr []string `json:"slr,random"`
    23  	Slo []string `json:"slo,omitempty"`
    24  
    25  	Mr map[string]interface{} `json:"mr"`
    26  	Mo map[string]interface{} `json:",omitempty"`
    27  }
    28  
    29  var optionalsExpected = `{
    30   "sr": "",
    31   "omitempty": 0,
    32   "slr": null,
    33   "mr": {}
    34  }`
    35  
    36  func TestOmitEmpty(t *testing.T) {
    37  	var o Optionals
    38  	o.Sw = "something"
    39  	o.Mr = map[string]interface{}{}
    40  	o.Mo = map[string]interface{}{}
    41  
    42  	got, err := MarshalIndent(&o, "", " ")
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  	if got := string(got); got != optionalsExpected {
    47  		t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)
    48  	}
    49  }
    50  
    51  type StringTag struct {
    52  	BoolStr bool   `json:",string"`
    53  	IntStr  int64  `json:",string"`
    54  	StrStr  string `json:",string"`
    55  }
    56  
    57  var stringTagExpected = `{
    58   "BoolStr": "true",
    59   "IntStr": "42",
    60   "StrStr": "\"xzbit\""
    61  }`
    62  
    63  func TestStringTag(t *testing.T) {
    64  	var s StringTag
    65  	s.BoolStr = true
    66  	s.IntStr = 42
    67  	s.StrStr = "xzbit"
    68  	got, err := MarshalIndent(&s, "", " ")
    69  	if err != nil {
    70  		t.Fatal(err)
    71  	}
    72  	if got := string(got); got != stringTagExpected {
    73  		t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected)
    74  	}
    75  
    76  	// Verify that it round-trips.
    77  	var s2 StringTag
    78  	err = NewDecoder(bytes.NewBuffer(got)).Decode(&s2)
    79  	if err != nil {
    80  		t.Fatalf("Decode: %v", err)
    81  	}
    82  	if !reflect.DeepEqual(s, s2) {
    83  		t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2)
    84  	}
    85  }
    86  
    87  // byte slices are special even if they're renamed types.
    88  type renamedByte byte
    89  type renamedByteSlice []byte
    90  type renamedRenamedByteSlice []renamedByte
    91  
    92  func TestEncodeRenamedByteSlice(t *testing.T) {
    93  	s := renamedByteSlice("abc")
    94  	result, err := Marshal(s)
    95  	if err != nil {
    96  		t.Fatal(err)
    97  	}
    98  	expect := `"YWJj"`
    99  	if string(result) != expect {
   100  		t.Errorf(" got %s want %s", result, expect)
   101  	}
   102  	r := renamedRenamedByteSlice("abc")
   103  	result, err = Marshal(r)
   104  	if err != nil {
   105  		t.Fatal(err)
   106  	}
   107  	if string(result) != expect {
   108  		t.Errorf(" got %s want %s", result, expect)
   109  	}
   110  }
   111  
   112  var unsupportedValues = []interface{}{
   113  	math.NaN(),
   114  	math.Inf(-1),
   115  	math.Inf(1),
   116  }
   117  
   118  func TestUnsupportedValues(t *testing.T) {
   119  	for _, v := range unsupportedValues {
   120  		if _, err := Marshal(v); err != nil {
   121  			if _, ok := err.(*UnsupportedValueError); !ok {
   122  				t.Errorf("for %v, got %T want UnsupportedValueError", v, err)
   123  			}
   124  		} else {
   125  			t.Errorf("for %v, expected error", v)
   126  		}
   127  	}
   128  }
   129  
   130  // Ref has Marshaler and Unmarshaler methods with pointer receiver.
   131  type Ref int
   132  
   133  func (*Ref) MarshalJSON() ([]byte, error) {
   134  	return []byte(`"ref"`), nil
   135  }
   136  
   137  func (r *Ref) UnmarshalJSON([]byte) error {
   138  	*r = 12
   139  	return nil
   140  }
   141  
   142  // Val has Marshaler methods with value receiver.
   143  type Val int
   144  
   145  func (Val) MarshalJSON() ([]byte, error) {
   146  	return []byte(`"val"`), nil
   147  }
   148  
   149  func TestRefValMarshal(t *testing.T) {
   150  	var s = struct {
   151  		R0 Ref
   152  		R1 *Ref
   153  		V0 Val
   154  		V1 *Val
   155  	}{
   156  		R0: 12,
   157  		R1: new(Ref),
   158  		V0: 13,
   159  		V1: new(Val),
   160  	}
   161  	const want = `{"R0":"ref","R1":"ref","V0":"val","V1":"val"}`
   162  	b, err := Marshal(&s)
   163  	if err != nil {
   164  		t.Fatalf("Marshal: %v", err)
   165  	}
   166  	if got := string(b); got != want {
   167  		t.Errorf("got %q, want %q", got, want)
   168  	}
   169  }
   170  
   171  // C implements Marshaler and returns unescaped JSON.
   172  type C int
   173  
   174  func (C) MarshalJSON() ([]byte, error) {
   175  	return []byte(`"<&>"`), nil
   176  }
   177  
   178  func TestMarshalerEscaping(t *testing.T) {
   179  	var c C
   180  	const want = `"\u003c\u0026\u003e"`
   181  	b, err := Marshal(c)
   182  	if err != nil {
   183  		t.Fatalf("Marshal: %v", err)
   184  	}
   185  	if got := string(b); got != want {
   186  		t.Errorf("got %q, want %q", got, want)
   187  	}
   188  }