OSDN Git Service

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