The Go Programming Language

Source file src/pkg/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	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.