github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/fix/testdata/reflect.encode.go.out (about)

     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  // The json package implements encoding and decoding of JSON objects as
     6  // defined in RFC 4627.
     7  package json
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/base64"
    12  	"os"
    13  	"reflect"
    14  	"runtime"
    15  	"sort"
    16  	"strconv"
    17  	"unicode"
    18  	"utf8"
    19  )
    20  
    21  // Marshal returns the JSON encoding of v.
    22  //
    23  // Marshal traverses the value v recursively.
    24  // If an encountered value implements the Marshaler interface,
    25  // Marshal calls its MarshalJSON method to produce JSON.
    26  //
    27  // Otherwise, Marshal uses the following type-dependent default encodings:
    28  //
    29  // Boolean values encode as JSON booleans.
    30  //
    31  // Floating point and integer values encode as JSON numbers.
    32  //
    33  // String values encode as JSON strings, with each invalid UTF-8 sequence
    34  // replaced by the encoding of the Unicode replacement character U+FFFD.
    35  //
    36  // Array and slice values encode as JSON arrays, except that
    37  // []byte encodes as a base64-encoded string.
    38  //
    39  // Struct values encode as JSON objects.  Each struct field becomes
    40  // a member of the object.  By default the object's key name is the
    41  // struct field name.  If the struct field has a non-empty tag consisting
    42  // of only Unicode letters, digits, and underscores, that tag will be used
    43  // as the name instead.  Only exported fields will be encoded.
    44  //
    45  // Map values encode as JSON objects.
    46  // The map's key type must be string; the object keys are used directly
    47  // as map keys.
    48  //
    49  // Pointer values encode as the value pointed to.
    50  // A nil pointer encodes as the null JSON object.
    51  //
    52  // Interface values encode as the value contained in the interface.
    53  // A nil interface value encodes as the null JSON object.
    54  //
    55  // Channel, complex, and function values cannot be encoded in JSON.
    56  // Attempting to encode such a value causes Marshal to return
    57  // an InvalidTypeError.
    58  //
    59  // JSON cannot represent cyclic data structures and Marshal does not
    60  // handle them.  Passing cyclic structures to Marshal will result in
    61  // an infinite recursion.
    62  //
    63  func Marshal(v interface{}) ([]byte, os.Error) {
    64  	e := &encodeState{}
    65  	err := e.marshal(v)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	return e.Bytes(), nil
    70  }
    71  
    72  // MarshalIndent is like Marshal but applies Indent to format the output.
    73  func MarshalIndent(v interface{}, prefix, indent string) ([]byte, os.Error) {
    74  	b, err := Marshal(v)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  	var buf bytes.Buffer
    79  	err = Indent(&buf, b, prefix, indent)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	return buf.Bytes(), nil
    84  }
    85  
    86  // MarshalForHTML is like Marshal but applies HTMLEscape to the output.
    87  func MarshalForHTML(v interface{}) ([]byte, os.Error) {
    88  	b, err := Marshal(v)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	var buf bytes.Buffer
    93  	HTMLEscape(&buf, b)
    94  	return buf.Bytes(), nil
    95  }
    96  
    97  // HTMLEscape appends to dst the JSON-encoded src with <, >, and &
    98  // characters inside string literals changed to \u003c, \u003e, \u0026
    99  // so that the JSON will be safe to embed inside HTML <script> tags.
   100  // For historical reasons, web browsers don't honor standard HTML
   101  // escaping within <script> tags, so an alternative JSON encoding must
   102  // be used.
   103  func HTMLEscape(dst *bytes.Buffer, src []byte) {
   104  	// < > & can only appear in string literals,
   105  	// so just scan the string one byte at a time.
   106  	start := 0
   107  	for i, c := range src {
   108  		if c == '<' || c == '>' || c == '&' {
   109  			if start < i {
   110  				dst.Write(src[start:i])
   111  			}
   112  			dst.WriteString(`\u00`)
   113  			dst.WriteByte(hex[c>>4])
   114  			dst.WriteByte(hex[c&0xF])
   115  			start = i + 1
   116  		}
   117  	}
   118  	if start < len(src) {
   119  		dst.Write(src[start:])
   120  	}
   121  }
   122  
   123  // Marshaler is the interface implemented by objects that
   124  // can marshal themselves into valid JSON.
   125  type Marshaler interface {
   126  	MarshalJSON() ([]byte, os.Error)
   127  }
   128  
   129  type UnsupportedTypeError struct {
   130  	Type reflect.Type
   131  }
   132  
   133  func (e *UnsupportedTypeError) String() string {
   134  	return "json: unsupported type: " + e.Type.String()
   135  }
   136  
   137  type InvalidUTF8Error struct {
   138  	S string
   139  }
   140  
   141  func (e *InvalidUTF8Error) String() string {
   142  	return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
   143  }
   144  
   145  type MarshalerError struct {
   146  	Type  reflect.Type
   147  	Error os.Error
   148  }
   149  
   150  func (e *MarshalerError) String() string {
   151  	return "json: error calling MarshalJSON for type " + e.Type.String() + ": " + e.Error.String()
   152  }
   153  
   154  type interfaceOrPtrValue interface {
   155  	IsNil() bool
   156  	Elem() reflect.Value
   157  }
   158  
   159  var hex = "0123456789abcdef"
   160  
   161  // An encodeState encodes JSON into a bytes.Buffer.
   162  type encodeState struct {
   163  	bytes.Buffer // accumulated output
   164  }
   165  
   166  func (e *encodeState) marshal(v interface{}) (err os.Error) {
   167  	defer func() {
   168  		if r := recover(); r != nil {
   169  			if _, ok := r.(runtime.Error); ok {
   170  				panic(r)
   171  			}
   172  			err = r.(os.Error)
   173  		}
   174  	}()
   175  	e.reflectValue(reflect.ValueOf(v))
   176  	return nil
   177  }
   178  
   179  func (e *encodeState) error(err os.Error) {
   180  	panic(err)
   181  }
   182  
   183  var byteSliceType = reflect.TypeOf([]byte(nil))
   184  
   185  func (e *encodeState) reflectValue(v reflect.Value) {
   186  	if !v.IsValid() {
   187  		e.WriteString("null")
   188  		return
   189  	}
   190  
   191  	if j, ok := v.Interface().(Marshaler); ok {
   192  		b, err := j.MarshalJSON()
   193  		if err == nil {
   194  			// copy JSON into buffer, checking validity.
   195  			err = Compact(&e.Buffer, b)
   196  		}
   197  		if err != nil {
   198  			e.error(&MarshalerError{v.Type(), err})
   199  		}
   200  		return
   201  	}
   202  
   203  	switch v.Kind() {
   204  	case reflect.Bool:
   205  		x := v.Bool()
   206  		if x {
   207  			e.WriteString("true")
   208  		} else {
   209  			e.WriteString("false")
   210  		}
   211  
   212  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   213  		e.WriteString(strconv.Itoa64(v.Int()))
   214  
   215  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   216  		e.WriteString(strconv.Uitoa64(v.Uint()))
   217  
   218  	case reflect.Float32, reflect.Float64:
   219  		e.WriteString(strconv.FtoaN(v.Float(), 'g', -1, v.Type().Bits()))
   220  
   221  	case reflect.String:
   222  		e.string(v.String())
   223  
   224  	case reflect.Struct:
   225  		e.WriteByte('{')
   226  		t := v.Type()
   227  		n := v.NumField()
   228  		first := true
   229  		for i := 0; i < n; i++ {
   230  			f := t.Field(i)
   231  			if f.PkgPath != "" {
   232  				continue
   233  			}
   234  			if first {
   235  				first = false
   236  			} else {
   237  				e.WriteByte(',')
   238  			}
   239  			if isValidTag(f.Tag) {
   240  				e.string(f.Tag)
   241  			} else {
   242  				e.string(f.Name)
   243  			}
   244  			e.WriteByte(':')
   245  			e.reflectValue(v.Field(i))
   246  		}
   247  		e.WriteByte('}')
   248  
   249  	case reflect.Map:
   250  		if v.Type().Key().Kind() != reflect.String {
   251  			e.error(&UnsupportedTypeError{v.Type()})
   252  		}
   253  		if v.IsNil() {
   254  			e.WriteString("null")
   255  			break
   256  		}
   257  		e.WriteByte('{')
   258  		var sv stringValues = v.MapKeys()
   259  		sort.Sort(sv)
   260  		for i, k := range sv {
   261  			if i > 0 {
   262  				e.WriteByte(',')
   263  			}
   264  			e.string(k.String())
   265  			e.WriteByte(':')
   266  			e.reflectValue(v.MapIndex(k))
   267  		}
   268  		e.WriteByte('}')
   269  
   270  	case reflect.Array, reflect.Slice:
   271  		if v.Type() == byteSliceType {
   272  			e.WriteByte('"')
   273  			s := v.Interface().([]byte)
   274  			if len(s) < 1024 {
   275  				// for small buffers, using Encode directly is much faster.
   276  				dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
   277  				base64.StdEncoding.Encode(dst, s)
   278  				e.Write(dst)
   279  			} else {
   280  				// for large buffers, avoid unnecessary extra temporary
   281  				// buffer space.
   282  				enc := base64.NewEncoder(base64.StdEncoding, e)
   283  				enc.Write(s)
   284  				enc.Close()
   285  			}
   286  			e.WriteByte('"')
   287  			break
   288  		}
   289  		e.WriteByte('[')
   290  		n := v.Len()
   291  		for i := 0; i < n; i++ {
   292  			if i > 0 {
   293  				e.WriteByte(',')
   294  			}
   295  			e.reflectValue(v.Index(i))
   296  		}
   297  		e.WriteByte(']')
   298  
   299  	case interfaceOrPtrValue:
   300  		if v.IsNil() {
   301  			e.WriteString("null")
   302  			return
   303  		}
   304  		e.reflectValue(v.Elem())
   305  
   306  	default:
   307  		e.error(&UnsupportedTypeError{v.Type()})
   308  	}
   309  	return
   310  }
   311  
   312  func isValidTag(s string) bool {
   313  	if s == "" {
   314  		return false
   315  	}
   316  	for _, c := range s {
   317  		if c != '_' && !unicode.IsLetter(c) && !unicode.IsDigit(c) {
   318  			return false
   319  		}
   320  	}
   321  	return true
   322  }
   323  
   324  // stringValues is a slice of reflect.Value holding *reflect.StringValue.
   325  // It implements the methods to sort by string.
   326  type stringValues []reflect.Value
   327  
   328  func (sv stringValues) Len() int           { return len(sv) }
   329  func (sv stringValues) Swap(i, j int)      { sv[i], sv[j] = sv[j], sv[i] }
   330  func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
   331  func (sv stringValues) get(i int) string   { return sv[i].String() }
   332  
   333  func (e *encodeState) string(s string) {
   334  	e.WriteByte('"')
   335  	start := 0
   336  	for i := 0; i < len(s); {
   337  		if b := s[i]; b < utf8.RuneSelf {
   338  			if 0x20 <= b && b != '\\' && b != '"' {
   339  				i++
   340  				continue
   341  			}
   342  			if start < i {
   343  				e.WriteString(s[start:i])
   344  			}
   345  			if b == '\\' || b == '"' {
   346  				e.WriteByte('\\')
   347  				e.WriteByte(b)
   348  			} else {
   349  				e.WriteString(`\u00`)
   350  				e.WriteByte(hex[b>>4])
   351  				e.WriteByte(hex[b&0xF])
   352  			}
   353  			i++
   354  			start = i
   355  			continue
   356  		}
   357  		c, size := utf8.DecodeRuneInString(s[i:])
   358  		if c == utf8.RuneError && size == 1 {
   359  			e.error(&InvalidUTF8Error{s})
   360  		}
   361  		i += size
   362  	}
   363  	if start < len(s) {
   364  		e.WriteString(s[start:])
   365  	}
   366  	e.WriteByte('"')
   367  }