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 }