OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / libgo / go / json / encode.go
1 // Copyright 2010 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 implements encoding and decoding of JSON objects as defined in
6 // RFC 4627.
7 //
8 // See "JSON and Go" for an introduction to this package:
9 // http://blog.golang.org/2011/01/json-and-go.html
10 package json
11
12 import (
13         "bytes"
14         "encoding/base64"
15         "reflect"
16         "runtime"
17         "sort"
18         "strconv"
19         "unicode"
20         "utf8"
21 )
22
23 // Marshal returns the JSON encoding of v.
24 //
25 // Marshal traverses the value v recursively.
26 // If an encountered value implements the Marshaler interface
27 // and is not a nil pointer, Marshal calls its MarshalJSON method
28 // to produce JSON.  The nil pointer exception is not strictly necessary
29 // but mimics a similar, necessary exception in the behavior of
30 // UnmarshalJSON.
31 //
32 // Otherwise, Marshal uses the following type-dependent default encodings:
33 //
34 // Boolean values encode as JSON booleans.
35 //
36 // Floating point and integer values encode as JSON numbers.
37 //
38 // String values encode as JSON strings, with each invalid UTF-8 sequence
39 // replaced by the encoding of the Unicode replacement character U+FFFD.
40 //
41 // Array and slice values encode as JSON arrays, except that
42 // []byte encodes as a base64-encoded string.
43 //
44 // Struct values encode as JSON objects. Each exported struct field
45 // becomes a member of the object unless
46 //   - the field's tag is "-", or
47 //   - the field is empty and its tag specifies the "omitempty" option.
48 // The empty values are false, 0, any
49 // nil pointer or interface value, and any array, slice, map, or string of
50 // length zero. The object's default key string is the struct field name
51 // but can be specified in the struct field's tag value. The "json" key in
52 // struct field's tag value is the key name, followed by an optional comma
53 // and options. Examples:
54 //
55 //   // Field is ignored by this package.
56 //   Field int `json:"-"`
57 //
58 //   // Field appears in JSON as key "myName".
59 //   Field int `json:"myName"`
60 //
61 //   // Field appears in JSON as key "myName" and
62 //   // the field is omitted from the object if its value is empty,
63 //   // as defined above.
64 //   Field int `json:"myName,omitempty"`
65 //
66 //   // Field appears in JSON as key "Field" (the default), but
67 //   // the field is skipped if empty.
68 //   // Note the leading comma.
69 //   Field int `json:",omitempty"`
70 //
71 // The "string" option signals that a field is stored as JSON inside a
72 // JSON-encoded string.  This extra level of encoding is sometimes
73 // used when communicating with JavaScript programs:
74 //
75 //    Int64String int64 `json:",string"`
76 //
77 // The key name will be used if it's a non-empty string consisting of
78 // only Unicode letters, digits, dollar signs, hyphens, and underscores.
79 //
80 // Map values encode as JSON objects.
81 // The map's key type must be string; the object keys are used directly
82 // as map keys.
83 //
84 // Pointer values encode as the value pointed to.
85 // A nil pointer encodes as the null JSON object.
86 //
87 // Interface values encode as the value contained in the interface.
88 // A nil interface value encodes as the null JSON object.
89 //
90 // Channel, complex, and function values cannot be encoded in JSON.
91 // Attempting to encode such a value causes Marshal to return
92 // an InvalidTypeError.
93 //
94 // JSON cannot represent cyclic data structures and Marshal does not
95 // handle them.  Passing cyclic structures to Marshal will result in
96 // an infinite recursion.
97 //
98 func Marshal(v interface{}) ([]byte, error) {
99         e := &encodeState{}
100         err := e.marshal(v)
101         if err != nil {
102                 return nil, err
103         }
104         return e.Bytes(), nil
105 }
106
107 // MarshalIndent is like Marshal but applies Indent to format the output.
108 func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
109         b, err := Marshal(v)
110         if err != nil {
111                 return nil, err
112         }
113         var buf bytes.Buffer
114         err = Indent(&buf, b, prefix, indent)
115         if err != nil {
116                 return nil, err
117         }
118         return buf.Bytes(), nil
119 }
120
121 // MarshalForHTML is like Marshal but applies HTMLEscape to the output.
122 func MarshalForHTML(v interface{}) ([]byte, error) {
123         b, err := Marshal(v)
124         if err != nil {
125                 return nil, err
126         }
127         var buf bytes.Buffer
128         HTMLEscape(&buf, b)
129         return buf.Bytes(), nil
130 }
131
132 // HTMLEscape appends to dst the JSON-encoded src with <, >, and &
133 // characters inside string literals changed to \u003c, \u003e, \u0026
134 // so that the JSON will be safe to embed inside HTML <script> tags.
135 // For historical reasons, web browsers don't honor standard HTML
136 // escaping within <script> tags, so an alternative JSON encoding must
137 // be used.
138 func HTMLEscape(dst *bytes.Buffer, src []byte) {
139         // < > & can only appear in string literals,
140         // so just scan the string one byte at a time.
141         start := 0
142         for i, c := range src {
143                 if c == '<' || c == '>' || c == '&' {
144                         if start < i {
145                                 dst.Write(src[start:i])
146                         }
147                         dst.WriteString(`\u00`)
148                         dst.WriteByte(hex[c>>4])
149                         dst.WriteByte(hex[c&0xF])
150                         start = i + 1
151                 }
152         }
153         if start < len(src) {
154                 dst.Write(src[start:])
155         }
156 }
157
158 // Marshaler is the interface implemented by objects that
159 // can marshal themselves into valid JSON.
160 type Marshaler interface {
161         MarshalJSON() ([]byte, error)
162 }
163
164 type UnsupportedTypeError struct {
165         Type reflect.Type
166 }
167
168 func (e *UnsupportedTypeError) Error() string {
169         return "json: unsupported type: " + e.Type.String()
170 }
171
172 type InvalidUTF8Error struct {
173         S string
174 }
175
176 func (e *InvalidUTF8Error) Error() string {
177         return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
178 }
179
180 type MarshalerError struct {
181         Type reflect.Type
182         Err  error
183 }
184
185 func (e *MarshalerError) Error() string {
186         return "json: error calling MarshalJSON for type " + e.Type.String() + ": " + e.Err.Error()
187 }
188
189 type interfaceOrPtrValue interface {
190         IsNil() bool
191         Elem() reflect.Value
192 }
193
194 var hex = "0123456789abcdef"
195
196 // An encodeState encodes JSON into a bytes.Buffer.
197 type encodeState struct {
198         bytes.Buffer // accumulated output
199 }
200
201 func (e *encodeState) marshal(v interface{}) (err error) {
202         defer func() {
203                 if r := recover(); r != nil {
204                         if _, ok := r.(runtime.Error); ok {
205                                 panic(r)
206                         }
207                         err = r.(error)
208                 }
209         }()
210         e.reflectValue(reflect.ValueOf(v))
211         return nil
212 }
213
214 func (e *encodeState) error(err error) {
215         panic(err)
216 }
217
218 var byteSliceType = reflect.TypeOf([]byte(nil))
219
220 func isEmptyValue(v reflect.Value) bool {
221         switch v.Kind() {
222         case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
223                 return v.Len() == 0
224         case reflect.Bool:
225                 return !v.Bool()
226         case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
227                 return v.Int() == 0
228         case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
229                 return v.Uint() == 0
230         case reflect.Float32, reflect.Float64:
231                 return v.Float() == 0
232         case reflect.Interface, reflect.Ptr:
233                 return v.IsNil()
234         }
235         return false
236 }
237
238 func (e *encodeState) reflectValue(v reflect.Value) {
239         e.reflectValueQuoted(v, false)
240 }
241
242 // reflectValueQuoted writes the value in v to the output.
243 // If quoted is true, the serialization is wrapped in a JSON string.
244 func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
245         if !v.IsValid() {
246                 e.WriteString("null")
247                 return
248         }
249
250         if j, ok := v.Interface().(Marshaler); ok && (v.Kind() != reflect.Ptr || !v.IsNil()) {
251                 b, err := j.MarshalJSON()
252                 if err == nil {
253                         // copy JSON into buffer, checking validity.
254                         err = Compact(&e.Buffer, b)
255                 }
256                 if err != nil {
257                         e.error(&MarshalerError{v.Type(), err})
258                 }
259                 return
260         }
261
262         writeString := (*encodeState).WriteString
263         if quoted {
264                 writeString = (*encodeState).string
265         }
266
267         switch v.Kind() {
268         case reflect.Bool:
269                 x := v.Bool()
270                 if x {
271                         writeString(e, "true")
272                 } else {
273                         writeString(e, "false")
274                 }
275
276         case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
277                 writeString(e, strconv.Itoa64(v.Int()))
278
279         case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
280                 writeString(e, strconv.Uitoa64(v.Uint()))
281
282         case reflect.Float32, reflect.Float64:
283                 writeString(e, strconv.FtoaN(v.Float(), 'g', -1, v.Type().Bits()))
284
285         case reflect.String:
286                 if quoted {
287                         sb, err := Marshal(v.String())
288                         if err != nil {
289                                 e.error(err)
290                         }
291                         e.string(string(sb))
292                 } else {
293                         e.string(v.String())
294                 }
295
296         case reflect.Struct:
297                 e.WriteByte('{')
298                 t := v.Type()
299                 n := v.NumField()
300                 first := true
301                 for i := 0; i < n; i++ {
302                         f := t.Field(i)
303                         if f.PkgPath != "" {
304                                 continue
305                         }
306                         tag, omitEmpty, quoted := f.Name, false, false
307                         if tv := f.Tag.Get("json"); tv != "" {
308                                 if tv == "-" {
309                                         continue
310                                 }
311                                 name, opts := parseTag(tv)
312                                 if isValidTag(name) {
313                                         tag = name
314                                 }
315                                 omitEmpty = opts.Contains("omitempty")
316                                 quoted = opts.Contains("string")
317                         }
318                         fieldValue := v.Field(i)
319                         if omitEmpty && isEmptyValue(fieldValue) {
320                                 continue
321                         }
322                         if first {
323                                 first = false
324                         } else {
325                                 e.WriteByte(',')
326                         }
327                         e.string(tag)
328                         e.WriteByte(':')
329                         e.reflectValueQuoted(fieldValue, quoted)
330                 }
331                 e.WriteByte('}')
332
333         case reflect.Map:
334                 if v.Type().Key().Kind() != reflect.String {
335                         e.error(&UnsupportedTypeError{v.Type()})
336                 }
337                 if v.IsNil() {
338                         e.WriteString("null")
339                         break
340                 }
341                 e.WriteByte('{')
342                 var sv stringValues = v.MapKeys()
343                 sort.Sort(sv)
344                 for i, k := range sv {
345                         if i > 0 {
346                                 e.WriteByte(',')
347                         }
348                         e.string(k.String())
349                         e.WriteByte(':')
350                         e.reflectValue(v.MapIndex(k))
351                 }
352                 e.WriteByte('}')
353
354         case reflect.Slice:
355                 if v.IsNil() {
356                         e.WriteString("null")
357                         break
358                 }
359                 // Slices can be marshalled as nil, but otherwise are handled
360                 // as arrays.
361                 fallthrough
362         case reflect.Array:
363                 if v.Type() == byteSliceType {
364                         e.WriteByte('"')
365                         s := v.Interface().([]byte)
366                         if len(s) < 1024 {
367                                 // for small buffers, using Encode directly is much faster.
368                                 dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
369                                 base64.StdEncoding.Encode(dst, s)
370                                 e.Write(dst)
371                         } else {
372                                 // for large buffers, avoid unnecessary extra temporary
373                                 // buffer space.
374                                 enc := base64.NewEncoder(base64.StdEncoding, e)
375                                 enc.Write(s)
376                                 enc.Close()
377                         }
378                         e.WriteByte('"')
379                         break
380                 }
381                 e.WriteByte('[')
382                 n := v.Len()
383                 for i := 0; i < n; i++ {
384                         if i > 0 {
385                                 e.WriteByte(',')
386                         }
387                         e.reflectValue(v.Index(i))
388                 }
389                 e.WriteByte(']')
390
391         case reflect.Interface, reflect.Ptr:
392                 if v.IsNil() {
393                         e.WriteString("null")
394                         return
395                 }
396                 e.reflectValue(v.Elem())
397
398         default:
399                 e.error(&UnsupportedTypeError{v.Type()})
400         }
401         return
402 }
403
404 func isValidTag(s string) bool {
405         if s == "" {
406                 return false
407         }
408         for _, c := range s {
409                 if c != '$' && c != '-' && c != '_' && !unicode.IsLetter(c) && !unicode.IsDigit(c) {
410                         return false
411                 }
412         }
413         return true
414 }
415
416 // stringValues is a slice of reflect.Value holding *reflect.StringValue.
417 // It implements the methods to sort by string.
418 type stringValues []reflect.Value
419
420 func (sv stringValues) Len() int           { return len(sv) }
421 func (sv stringValues) Swap(i, j int)      { sv[i], sv[j] = sv[j], sv[i] }
422 func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
423 func (sv stringValues) get(i int) string   { return sv[i].String() }
424
425 func (e *encodeState) string(s string) (int, error) {
426         len0 := e.Len()
427         e.WriteByte('"')
428         start := 0
429         for i := 0; i < len(s); {
430                 if b := s[i]; b < utf8.RuneSelf {
431                         if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' {
432                                 i++
433                                 continue
434                         }
435                         if start < i {
436                                 e.WriteString(s[start:i])
437                         }
438                         switch b {
439                         case '\\', '"':
440                                 e.WriteByte('\\')
441                                 e.WriteByte(b)
442                         case '\n':
443                                 e.WriteByte('\\')
444                                 e.WriteByte('n')
445                         case '\r':
446                                 e.WriteByte('\\')
447                                 e.WriteByte('r')
448                         default:
449                                 // This encodes bytes < 0x20 except for \n and \r,
450                                 // as well as < and >. The latter are escaped because they
451                                 // can lead to security holes when user-controlled strings
452                                 // are rendered into JSON and served to some browsers.
453                                 e.WriteString(`\u00`)
454                                 e.WriteByte(hex[b>>4])
455                                 e.WriteByte(hex[b&0xF])
456                         }
457                         i++
458                         start = i
459                         continue
460                 }
461                 c, size := utf8.DecodeRuneInString(s[i:])
462                 if c == utf8.RuneError && size == 1 {
463                         e.error(&InvalidUTF8Error{s})
464                 }
465                 i += size
466         }
467         if start < len(s) {
468                 e.WriteString(s[start:])
469         }
470         e.WriteByte('"')
471         return e.Len() - len0, nil
472 }