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.
15 type Optionals
struct {
17 So
string `json:"so,omitempty"`
20 Ir
int `json:"omitempty"` // actually named omitempty, not an option
21 Io
int `json:"io,omitempty"`
23 Slr
[]string `json:"slr,random"`
24 Slo
[]string `json:"slo,omitempty"`
26 Mr
map[string]interface{} `json:"mr"`
27 Mo
map[string]interface{} `json:",omitempty"`
29 Fr
float64 `json:"fr"`
30 Fo
float64 `json:"fo,omitempty"`
33 Bo
bool `json:"bo,omitempty"`
36 Uo
uint `json:"uo,omitempty"`
38 Str
struct{} `json:"str"`
39 Sto
struct{} `json:"sto,omitempty"`
42 var optionalsExpected
= `{
54 func TestOmitEmpty(t
*testing
.T
) {
57 o
.Mr
= map[string]interface{}{}
58 o
.Mo
= map[string]interface{}{}
60 got
, err
:= MarshalIndent(&o
, "", " ")
64 if got
:= string(got
); got
!= optionalsExpected
{
65 t
.Errorf(" got: %s\nwant: %s\n", got
, optionalsExpected
)
69 type StringTag
struct {
70 BoolStr
bool `json:",string"`
71 IntStr
int64 `json:",string"`
72 StrStr
string `json:",string"`
75 var stringTagExpected
= `{
81 func TestStringTag(t
*testing
.T
) {
86 got
, err
:= MarshalIndent(&s
, "", " ")
90 if got
:= string(got
); got
!= stringTagExpected
{
91 t
.Fatalf(" got: %s\nwant: %s\n", got
, stringTagExpected
)
94 // Verify that it round-trips.
96 err
= NewDecoder(bytes
.NewBuffer(got
)).Decode(&s2
)
98 t
.Fatalf("Decode: %v", err
)
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
)
105 // byte slices are special even if they're renamed types.
106 type renamedByte
byte
107 type renamedByteSlice
[]byte
108 type renamedRenamedByteSlice
[]renamedByte
110 func TestEncodeRenamedByteSlice(t
*testing
.T
) {
111 s
:= renamedByteSlice("abc")
112 result
, err
:= Marshal(s
)
117 if string(result
) != expect
{
118 t
.Errorf(" got %s want %s", result
, expect
)
120 r
:= renamedRenamedByteSlice("abc")
121 result
, err
= Marshal(r
)
125 if string(result
) != expect
{
126 t
.Errorf(" got %s want %s", result
, expect
)
130 var unsupportedValues
= []interface{}{
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
)
143 t
.Errorf("for %v, expected error", v
)
148 // Ref has Marshaler and Unmarshaler methods with pointer receiver.
151 func (*Ref
) MarshalJSON() ([]byte, error
) {
152 return []byte(`"ref"`), nil
155 func (r
*Ref
) UnmarshalJSON([]byte) error
{
160 // Val has Marshaler methods with value receiver.
163 func (Val
) MarshalJSON() ([]byte, error
) {
164 return []byte(`"val"`), nil
167 // RefText has Marshaler and Unmarshaler methods with pointer receiver.
170 func (*RefText
) MarshalText() ([]byte, error
) {
171 return []byte(`"ref"`), nil
174 func (r
*RefText
) UnmarshalText([]byte) error
{
179 // ValText has Marshaler methods with value receiver.
182 func (ValText
) MarshalText() ([]byte, error
) {
183 return []byte(`"val"`), nil
186 func TestRefValMarshal(t
*testing
.T
) {
206 const want
= `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`
207 b
, err
:= Marshal(&s
)
209 t
.Fatalf("Marshal: %v", err
)
211 if got
:= string(b
); got
!= want
{
212 t
.Errorf("got %q, want %q", got
, want
)
216 // C implements Marshaler and returns unescaped JSON.
219 func (C
) MarshalJSON() ([]byte, error
) {
220 return []byte(`"<&>"`), nil
223 // CText implements Marshaler and returns unescaped text.
226 func (CText
) MarshalText() ([]byte, error
) {
227 return []byte(`"<&>"`), nil
230 func TestMarshalerEscaping(t
*testing
.T
) {
232 want
:= `"\u003c\u0026\u003e"`
235 t
.Fatalf("Marshal(c): %v", err
)
237 if got
:= string(b
); got
!= want
{
238 t
.Errorf("Marshal(c) = %#q, want %#q", got
, want
)
242 want
= `"\"\u003c\u0026\u003e\""`
245 t
.Fatalf("Marshal(ct): %v", err
)
247 if got
:= string(b
); got
!= want
{
248 t
.Errorf("Marshal(ct) = %#q, want %#q", got
, want
)
254 type MyStruct
struct {
258 func TestAnonymousNonstruct(t
*testing
.T
) {
261 const want
= `{"IntType":11}`
265 t
.Fatalf("Marshal: %v", err
)
267 if got
:= string(b
); got
!= want
{
268 t
.Errorf("got %q, want %q", got
, want
)
285 // Legal Go: We never use the repeated embedded field (S).
293 func TestEmbeddedBug(t
*testing
.T
) {
300 t
.Fatal("Marshal:", err
)
305 t
.Fatalf("Marshal: got %s want %s", got
, want
)
307 // Now check that the duplicate field, S, does not appear.
313 t
.Fatal("Marshal:", err
)
318 t
.Fatalf("Marshal: got %s want %s", got
, want
)
322 type BugD
struct { // Same as BugA after tagging.
323 XXX
string `json:"S"`
326 // BugD's tagged S field should dominate BugA's.
332 // Test that a field with a tag dominates untagged fields.
333 func TestTaggedFieldDominates(t
*testing
.T
) {
340 t
.Fatal("Marshal:", err
)
342 want
:= `{"S":"BugD"}`
345 t
.Fatalf("Marshal: got %s want %s", got
, want
)
349 // There are no tags here, so S should not appear.
353 BugY
// Contains a tagged S field through BugD; should not dominate.
356 func TestDuplicatedFieldDisappears(t
*testing
.T
) {
367 t
.Fatal("Marshal:", err
)
372 t
.Fatalf("Marshal: got %s want %s", got
, want
)
376 func TestStringBytes(t
*testing
.T
) {
377 // Test that encodeState.stringBytes and encodeState.string use the same encoding.
380 for i
:= '\u0000'; i
<= unicode
.MaxRune
; i
++ {
383 s
:= string(r
) + "\xff\xff\xffhello" // some invalid UTF-8 too
384 _
, err
:= es
.string(s
)
389 esBytes
:= &encodeState
{}
390 _
, err
= esBytes
.stringBytes([]byte(s
))
395 enc
:= es
.Buffer
.String()
396 encBytes
:= esBytes
.Buffer
.String()
399 for i
< len(enc
) && i
< len(encBytes
) && enc
[i
] == encBytes
[i
] {
403 encBytes
= encBytes
[i
:]
405 for i
< len(enc
) && i
< len(encBytes
) && enc
[len(enc
)-i
-1] == encBytes
[len(encBytes
)-i
-1] {
408 enc
= enc
[:len(enc
)-i
]
409 encBytes
= encBytes
[:len(encBytes
)-i
]
412 enc
= enc
[:20] + "..."
414 if len(encBytes
) > 20 {
415 encBytes
= encBytes
[:20] + "..."
418 t
.Errorf("encodings differ at %#q vs %#q", enc
, encBytes
)
422 func TestIssue6458(t
*testing
.T
) {
426 x
:= Foo
{RawMessage(`"foo"`)}
428 b
, err
:= Marshal(&x
)
432 if want
:= `{"M":"foo"}`; string(b
) != want
{
433 t
.Errorf("Marshal(&x) = %#q; want %#q", b
, want
)
441 if want
:= `{"M":"ImZvbyI="}`; string(b
) != want
{
442 t
.Errorf("Marshal(x) = %#q; want %#q", b
, want
)
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())