Run Format

Source file src/pkg/encoding/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. The mapping between JSON objects and Go values is described
     7	// in the documentation for the Marshal and Unmarshal functions.
     8	//
     9	// See "JSON and Go" for an introduction to this package:
    10	// http://golang.org/doc/articles/json_and_go.html
    11	package json
    12	
    13	import (
    14		"bytes"
    15		"encoding/base64"
    16		"math"
    17		"reflect"
    18		"runtime"
    19		"sort"
    20		"strconv"
    21		"strings"
    22		"sync"
    23		"unicode"
    24		"unicode/utf8"
    25	)
    26	
    27	// Marshal returns the JSON encoding of v.
    28	//
    29	// Marshal traverses the value v recursively.
    30	// If an encountered value implements the Marshaler interface
    31	// and is not a nil pointer, Marshal calls its MarshalJSON method
    32	// to produce JSON.  The nil pointer exception is not strictly necessary
    33	// but mimics a similar, necessary exception in the behavior of
    34	// UnmarshalJSON.
    35	//
    36	// Otherwise, Marshal uses the following type-dependent default encodings:
    37	//
    38	// Boolean values encode as JSON booleans.
    39	//
    40	// Floating point, integer, and Number values encode as JSON numbers.
    41	//
    42	// String values encode as JSON strings. InvalidUTF8Error will be returned
    43	// if an invalid UTF-8 sequence is encountered.
    44	// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
    45	// to keep some browsers from misinterpreting JSON output as HTML.
    46	//
    47	// Array and slice values encode as JSON arrays, except that
    48	// []byte encodes as a base64-encoded string, and a nil slice
    49	// encodes as the null JSON object.
    50	//
    51	// Struct values encode as JSON objects. Each exported struct field
    52	// becomes a member of the object unless
    53	//   - the field's tag is "-", or
    54	//   - the field is empty and its tag specifies the "omitempty" option.
    55	// The empty values are false, 0, any
    56	// nil pointer or interface value, and any array, slice, map, or string of
    57	// length zero. The object's default key string is the struct field name
    58	// but can be specified in the struct field's tag value. The "json" key in
    59	// the struct field's tag value is the key name, followed by an optional comma
    60	// and options. Examples:
    61	//
    62	//   // Field is ignored by this package.
    63	//   Field int `json:"-"`
    64	//
    65	//   // Field appears in JSON as key "myName".
    66	//   Field int `json:"myName"`
    67	//
    68	//   // Field appears in JSON as key "myName" and
    69	//   // the field is omitted from the object if its value is empty,
    70	//   // as defined above.
    71	//   Field int `json:"myName,omitempty"`
    72	//
    73	//   // Field appears in JSON as key "Field" (the default), but
    74	//   // the field is skipped if empty.
    75	//   // Note the leading comma.
    76	//   Field int `json:",omitempty"`
    77	//
    78	// The "string" option signals that a field is stored as JSON inside a
    79	// JSON-encoded string. It applies only to fields of string, floating point,
    80	// or integer types. This extra level of encoding is sometimes used when
    81	// communicating with JavaScript programs:
    82	//
    83	//    Int64String int64 `json:",string"`
    84	//
    85	// The key name will be used if it's a non-empty string consisting of
    86	// only Unicode letters, digits, dollar signs, percent signs, hyphens,
    87	// underscores and slashes.
    88	//
    89	// Anonymous struct fields are usually marshaled as if their inner exported fields
    90	// were fields in the outer struct, subject to the usual Go visibility rules amended
    91	// as described in the next paragraph.
    92	// An anonymous struct field with a name given in its JSON tag is treated as
    93	// having that name, rather than being anonymous.
    94	//
    95	// The Go visibility rules for struct fields are amended for JSON when
    96	// deciding which field to marshal or unmarshal. If there are
    97	// multiple fields at the same level, and that level is the least
    98	// nested (and would therefore be the nesting level selected by the
    99	// usual Go rules), the following extra rules apply:
   100	//
   101	// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
   102	// even if there are multiple untagged fields that would otherwise conflict.
   103	// 2) If there is exactly one field (tagged or not according to the first rule), that is selected.
   104	// 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
   105	//
   106	// Handling of anonymous struct fields is new in Go 1.1.
   107	// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
   108	// an anonymous struct field in both current and earlier versions, give the field
   109	// a JSON tag of "-".
   110	//
   111	// Map values encode as JSON objects.
   112	// The map's key type must be string; the object keys are used directly
   113	// as map keys.
   114	//
   115	// Pointer values encode as the value pointed to.
   116	// A nil pointer encodes as the null JSON object.
   117	//
   118	// Interface values encode as the value contained in the interface.
   119	// A nil interface value encodes as the null JSON object.
   120	//
   121	// Channel, complex, and function values cannot be encoded in JSON.
   122	// Attempting to encode such a value causes Marshal to return
   123	// an UnsupportedTypeError.
   124	//
   125	// JSON cannot represent cyclic data structures and Marshal does not
   126	// handle them.  Passing cyclic structures to Marshal will result in
   127	// an infinite recursion.
   128	//
   129	func Marshal(v interface{}) ([]byte, error) {
   130		e := &encodeState{}
   131		err := e.marshal(v)
   132		if err != nil {
   133			return nil, err
   134		}
   135		return e.Bytes(), nil
   136	}
   137	
   138	// MarshalIndent is like Marshal but applies Indent to format the output.
   139	func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
   140		b, err := Marshal(v)
   141		if err != nil {
   142			return nil, err
   143		}
   144		var buf bytes.Buffer
   145		err = Indent(&buf, b, prefix, indent)
   146		if err != nil {
   147			return nil, err
   148		}
   149		return buf.Bytes(), nil
   150	}
   151	
   152	// HTMLEscape appends to dst the JSON-encoded src with <, >, and &
   153	// characters inside string literals changed to \u003c, \u003e, \u0026
   154	// so that the JSON will be safe to embed inside HTML <script> tags.
   155	// For historical reasons, web browsers don't honor standard HTML
   156	// escaping within <script> tags, so an alternative JSON encoding must
   157	// be used.
   158	func HTMLEscape(dst *bytes.Buffer, src []byte) {
   159		// < > & can only appear in string literals,
   160		// so just scan the string one byte at a time.
   161		start := 0
   162		for i, c := range src {
   163			if c == '<' || c == '>' || c == '&' {
   164				if start < i {
   165					dst.Write(src[start:i])
   166				}
   167				dst.WriteString(`\u00`)
   168				dst.WriteByte(hex[c>>4])
   169				dst.WriteByte(hex[c&0xF])
   170				start = i + 1
   171			}
   172		}
   173		if start < len(src) {
   174			dst.Write(src[start:])
   175		}
   176	}
   177	
   178	// Marshaler is the interface implemented by objects that
   179	// can marshal themselves into valid JSON.
   180	type Marshaler interface {
   181		MarshalJSON() ([]byte, error)
   182	}
   183	
   184	// An UnsupportedTypeError is returned by Marshal when attempting
   185	// to encode an unsupported value type.
   186	type UnsupportedTypeError struct {
   187		Type reflect.Type
   188	}
   189	
   190	func (e *UnsupportedTypeError) Error() string {
   191		return "json: unsupported type: " + e.Type.String()
   192	}
   193	
   194	type UnsupportedValueError struct {
   195		Value reflect.Value
   196		Str   string
   197	}
   198	
   199	func (e *UnsupportedValueError) Error() string {
   200		return "json: unsupported value: " + e.Str
   201	}
   202	
   203	// An InvalidUTF8Error is returned by Marshal when attempting
   204	// to encode a string value with invalid UTF-8 sequences.
   205	type InvalidUTF8Error struct {
   206		S string // the whole string value that caused the error
   207	}
   208	
   209	func (e *InvalidUTF8Error) Error() string {
   210		return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
   211	}
   212	
   213	type MarshalerError struct {
   214		Type reflect.Type
   215		Err  error
   216	}
   217	
   218	func (e *MarshalerError) Error() string {
   219		return "json: error calling MarshalJSON for type " + e.Type.String() + ": " + e.Err.Error()
   220	}
   221	
   222	var hex = "0123456789abcdef"
   223	
   224	// An encodeState encodes JSON into a bytes.Buffer.
   225	type encodeState struct {
   226		bytes.Buffer // accumulated output
   227		scratch      [64]byte
   228	}
   229	
   230	func (e *encodeState) marshal(v interface{}) (err error) {
   231		defer func() {
   232			if r := recover(); r != nil {
   233				if _, ok := r.(runtime.Error); ok {
   234					panic(r)
   235				}
   236				err = r.(error)
   237			}
   238		}()
   239		e.reflectValue(reflect.ValueOf(v))
   240		return nil
   241	}
   242	
   243	func (e *encodeState) error(err error) {
   244		panic(err)
   245	}
   246	
   247	var byteSliceType = reflect.TypeOf([]byte(nil))
   248	
   249	func isEmptyValue(v reflect.Value) bool {
   250		switch v.Kind() {
   251		case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
   252			return v.Len() == 0
   253		case reflect.Bool:
   254			return !v.Bool()
   255		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   256			return v.Int() == 0
   257		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   258			return v.Uint() == 0
   259		case reflect.Float32, reflect.Float64:
   260			return v.Float() == 0
   261		case reflect.Interface, reflect.Ptr:
   262			return v.IsNil()
   263		}
   264		return false
   265	}
   266	
   267	func (e *encodeState) reflectValue(v reflect.Value) {
   268		e.reflectValueQuoted(v, false)
   269	}
   270	
   271	// reflectValueQuoted writes the value in v to the output.
   272	// If quoted is true, the serialization is wrapped in a JSON string.
   273	func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
   274		if !v.IsValid() {
   275			e.WriteString("null")
   276			return
   277		}
   278	
   279		m, ok := v.Interface().(Marshaler)
   280		if !ok {
   281			// T doesn't match the interface. Check against *T too.
   282			if v.Kind() != reflect.Ptr && v.CanAddr() {
   283				m, ok = v.Addr().Interface().(Marshaler)
   284				if ok {
   285					v = v.Addr()
   286				}
   287			}
   288		}
   289		if ok && (v.Kind() != reflect.Ptr || !v.IsNil()) {
   290			b, err := m.MarshalJSON()
   291			if err == nil {
   292				// copy JSON into buffer, checking validity.
   293				err = compact(&e.Buffer, b, true)
   294			}
   295			if err != nil {
   296				e.error(&MarshalerError{v.Type(), err})
   297			}
   298			return
   299		}
   300	
   301		writeString := (*encodeState).WriteString
   302		if quoted {
   303			writeString = (*encodeState).string
   304		}
   305	
   306		switch v.Kind() {
   307		case reflect.Bool:
   308			x := v.Bool()
   309			if x {
   310				writeString(e, "true")
   311			} else {
   312				writeString(e, "false")
   313			}
   314	
   315		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   316			b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
   317			if quoted {
   318				writeString(e, string(b))
   319			} else {
   320				e.Write(b)
   321			}
   322		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   323			b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
   324			if quoted {
   325				writeString(e, string(b))
   326			} else {
   327				e.Write(b)
   328			}
   329		case reflect.Float32, reflect.Float64:
   330			f := v.Float()
   331			if math.IsInf(f, 0) || math.IsNaN(f) {
   332				e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, v.Type().Bits())})
   333			}
   334			b := strconv.AppendFloat(e.scratch[:0], f, 'g', -1, v.Type().Bits())
   335			if quoted {
   336				writeString(e, string(b))
   337			} else {
   338				e.Write(b)
   339			}
   340		case reflect.String:
   341			if v.Type() == numberType {
   342				numStr := v.String()
   343				if numStr == "" {
   344					numStr = "0" // Number's zero-val
   345				}
   346				e.WriteString(numStr)
   347				break
   348			}
   349			if quoted {
   350				sb, err := Marshal(v.String())
   351				if err != nil {
   352					e.error(err)
   353				}
   354				e.string(string(sb))
   355			} else {
   356				e.string(v.String())
   357			}
   358	
   359		case reflect.Struct:
   360			e.WriteByte('{')
   361			first := true
   362			for _, f := range cachedTypeFields(v.Type()) {
   363				fv := fieldByIndex(v, f.index)
   364				if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) {
   365					continue
   366				}
   367				if first {
   368					first = false
   369				} else {
   370					e.WriteByte(',')
   371				}
   372				e.string(f.name)
   373				e.WriteByte(':')
   374				e.reflectValueQuoted(fv, f.quoted)
   375			}
   376			e.WriteByte('}')
   377	
   378		case reflect.Map:
   379			if v.Type().Key().Kind() != reflect.String {
   380				e.error(&UnsupportedTypeError{v.Type()})
   381			}
   382			if v.IsNil() {
   383				e.WriteString("null")
   384				break
   385			}
   386			e.WriteByte('{')
   387			var sv stringValues = v.MapKeys()
   388			sort.Sort(sv)
   389			for i, k := range sv {
   390				if i > 0 {
   391					e.WriteByte(',')
   392				}
   393				e.string(k.String())
   394				e.WriteByte(':')
   395				e.reflectValue(v.MapIndex(k))
   396			}
   397			e.WriteByte('}')
   398	
   399		case reflect.Slice:
   400			if v.IsNil() {
   401				e.WriteString("null")
   402				break
   403			}
   404			if v.Type().Elem().Kind() == reflect.Uint8 {
   405				// Byte slices get special treatment; arrays don't.
   406				s := v.Bytes()
   407				e.WriteByte('"')
   408				if len(s) < 1024 {
   409					// for small buffers, using Encode directly is much faster.
   410					dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
   411					base64.StdEncoding.Encode(dst, s)
   412					e.Write(dst)
   413				} else {
   414					// for large buffers, avoid unnecessary extra temporary
   415					// buffer space.
   416					enc := base64.NewEncoder(base64.StdEncoding, e)
   417					enc.Write(s)
   418					enc.Close()
   419				}
   420				e.WriteByte('"')
   421				break
   422			}
   423			// Slices can be marshalled as nil, but otherwise are handled
   424			// as arrays.
   425			fallthrough
   426		case reflect.Array:
   427			e.WriteByte('[')
   428			n := v.Len()
   429			for i := 0; i < n; i++ {
   430				if i > 0 {
   431					e.WriteByte(',')
   432				}
   433				e.reflectValue(v.Index(i))
   434			}
   435			e.WriteByte(']')
   436	
   437		case reflect.Interface, reflect.Ptr:
   438			if v.IsNil() {
   439				e.WriteString("null")
   440				return
   441			}
   442			e.reflectValue(v.Elem())
   443	
   444		default:
   445			e.error(&UnsupportedTypeError{v.Type()})
   446		}
   447		return
   448	}
   449	
   450	func isValidTag(s string) bool {
   451		if s == "" {
   452			return false
   453		}
   454		for _, c := range s {
   455			switch {
   456			case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
   457				// Backslash and quote chars are reserved, but
   458				// otherwise any punctuation chars are allowed
   459				// in a tag name.
   460			default:
   461				if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
   462					return false
   463				}
   464			}
   465		}
   466		return true
   467	}
   468	
   469	func fieldByIndex(v reflect.Value, index []int) reflect.Value {
   470		for _, i := range index {
   471			if v.Kind() == reflect.Ptr {
   472				if v.IsNil() {
   473					return reflect.Value{}
   474				}
   475				v = v.Elem()
   476			}
   477			v = v.Field(i)
   478		}
   479		return v
   480	}
   481	
   482	// stringValues is a slice of reflect.Value holding *reflect.StringValue.
   483	// It implements the methods to sort by string.
   484	type stringValues []reflect.Value
   485	
   486	func (sv stringValues) Len() int           { return len(sv) }
   487	func (sv stringValues) Swap(i, j int)      { sv[i], sv[j] = sv[j], sv[i] }
   488	func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
   489	func (sv stringValues) get(i int) string   { return sv[i].String() }
   490	
   491	func (e *encodeState) string(s string) (int, error) {
   492		len0 := e.Len()
   493		e.WriteByte('"')
   494		start := 0
   495		for i := 0; i < len(s); {
   496			if b := s[i]; b < utf8.RuneSelf {
   497				if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' {
   498					i++
   499					continue
   500				}
   501				if start < i {
   502					e.WriteString(s[start:i])
   503				}
   504				switch b {
   505				case '\\', '"':
   506					e.WriteByte('\\')
   507					e.WriteByte(b)
   508				case '\n':
   509					e.WriteByte('\\')
   510					e.WriteByte('n')
   511				case '\r':
   512					e.WriteByte('\\')
   513					e.WriteByte('r')
   514				default:
   515					// This encodes bytes < 0x20 except for \n and \r,
   516					// as well as < and >. The latter are escaped because they
   517					// can lead to security holes when user-controlled strings
   518					// are rendered into JSON and served to some browsers.
   519					e.WriteString(`\u00`)
   520					e.WriteByte(hex[b>>4])
   521					e.WriteByte(hex[b&0xF])
   522				}
   523				i++
   524				start = i
   525				continue
   526			}
   527			c, size := utf8.DecodeRuneInString(s[i:])
   528			if c == utf8.RuneError && size == 1 {
   529				e.error(&InvalidUTF8Error{s})
   530			}
   531			i += size
   532		}
   533		if start < len(s) {
   534			e.WriteString(s[start:])
   535		}
   536		e.WriteByte('"')
   537		return e.Len() - len0, nil
   538	}
   539	
   540	// A field represents a single field found in a struct.
   541	type field struct {
   542		name      string
   543		tag       bool
   544		index     []int
   545		typ       reflect.Type
   546		omitEmpty bool
   547		quoted    bool
   548	}
   549	
   550	// byName sorts field by name, breaking ties with depth,
   551	// then breaking ties with "name came from json tag", then
   552	// breaking ties with index sequence.
   553	type byName []field
   554	
   555	func (x byName) Len() int { return len(x) }
   556	
   557	func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
   558	
   559	func (x byName) Less(i, j int) bool {
   560		if x[i].name != x[j].name {
   561			return x[i].name < x[j].name
   562		}
   563		if len(x[i].index) != len(x[j].index) {
   564			return len(x[i].index) < len(x[j].index)
   565		}
   566		if x[i].tag != x[j].tag {
   567			return x[i].tag
   568		}
   569		return byIndex(x).Less(i, j)
   570	}
   571	
   572	// byIndex sorts field by index sequence.
   573	type byIndex []field
   574	
   575	func (x byIndex) Len() int { return len(x) }
   576	
   577	func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
   578	
   579	func (x byIndex) Less(i, j int) bool {
   580		for k, xik := range x[i].index {
   581			if k >= len(x[j].index) {
   582				return false
   583			}
   584			if xik != x[j].index[k] {
   585				return xik < x[j].index[k]
   586			}
   587		}
   588		return len(x[i].index) < len(x[j].index)
   589	}
   590	
   591	// typeFields returns a list of fields that JSON should recognize for the given type.
   592	// The algorithm is breadth-first search over the set of structs to include - the top struct
   593	// and then any reachable anonymous structs.
   594	func typeFields(t reflect.Type) []field {
   595		// Anonymous fields to explore at the current level and the next.
   596		current := []field{}
   597		next := []field{{typ: t}}
   598	
   599		// Count of queued names for current level and the next.
   600		count := map[reflect.Type]int{}
   601		nextCount := map[reflect.Type]int{}
   602	
   603		// Types already visited at an earlier level.
   604		visited := map[reflect.Type]bool{}
   605	
   606		// Fields found.
   607		var fields []field
   608	
   609		for len(next) > 0 {
   610			current, next = next, current[:0]
   611			count, nextCount = nextCount, map[reflect.Type]int{}
   612	
   613			for _, f := range current {
   614				if visited[f.typ] {
   615					continue
   616				}
   617				visited[f.typ] = true
   618	
   619				// Scan f.typ for fields to include.
   620				for i := 0; i < f.typ.NumField(); i++ {
   621					sf := f.typ.Field(i)
   622					if sf.PkgPath != "" { // unexported
   623						continue
   624					}
   625					tag := sf.Tag.Get("json")
   626					if tag == "-" {
   627						continue
   628					}
   629					name, opts := parseTag(tag)
   630					if !isValidTag(name) {
   631						name = ""
   632					}
   633					index := make([]int, len(f.index)+1)
   634					copy(index, f.index)
   635					index[len(f.index)] = i
   636	
   637					ft := sf.Type
   638					if ft.Name() == "" && ft.Kind() == reflect.Ptr {
   639						// Follow pointer.
   640						ft = ft.Elem()
   641					}
   642	
   643					// Record found field and index sequence.
   644					if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
   645						tagged := name != ""
   646						if name == "" {
   647							name = sf.Name
   648						}
   649						fields = append(fields, field{name, tagged, index, ft,
   650							opts.Contains("omitempty"), opts.Contains("string")})
   651						if count[f.typ] > 1 {
   652							// If there were multiple instances, add a second,
   653							// so that the annihilation code will see a duplicate.
   654							// It only cares about the distinction between 1 or 2,
   655							// so don't bother generating any more copies.
   656							fields = append(fields, fields[len(fields)-1])
   657						}
   658						continue
   659					}
   660	
   661					// Record new anonymous struct to explore in next round.
   662					nextCount[ft]++
   663					if nextCount[ft] == 1 {
   664						next = append(next, field{name: ft.Name(), index: index, typ: ft})
   665					}
   666				}
   667			}
   668		}
   669	
   670		sort.Sort(byName(fields))
   671	
   672		// Delete all fields that are hidden by the Go rules for embedded fields,
   673		// except that fields with JSON tags are promoted.
   674	
   675		// The fields are sorted in primary order of name, secondary order
   676		// of field index length. Loop over names; for each name, delete
   677		// hidden fields by choosing the one dominant field that survives.
   678		out := fields[:0]
   679		for advance, i := 0, 0; i < len(fields); i += advance {
   680			// One iteration per name.
   681			// Find the sequence of fields with the name of this first field.
   682			fi := fields[i]
   683			name := fi.name
   684			for advance = 1; i+advance < len(fields); advance++ {
   685				fj := fields[i+advance]
   686				if fj.name != name {
   687					break
   688				}
   689			}
   690			if advance == 1 { // Only one field with this name
   691				out = append(out, fi)
   692				continue
   693			}
   694			dominant, ok := dominantField(fields[i : i+advance])
   695			if ok {
   696				out = append(out, dominant)
   697			}
   698		}
   699	
   700		fields = out
   701		sort.Sort(byIndex(fields))
   702	
   703		return fields
   704	}
   705	
   706	// dominantField looks through the fields, all of which are known to
   707	// have the same name, to find the single field that dominates the
   708	// others using Go's embedding rules, modified by the presence of
   709	// JSON tags. If there are multiple top-level fields, the boolean
   710	// will be false: This condition is an error in Go and we skip all
   711	// the fields.
   712	func dominantField(fields []field) (field, bool) {
   713		// The fields are sorted in increasing index-length order. The winner
   714		// must therefore be one with the shortest index length. Drop all
   715		// longer entries, which is easy: just truncate the slice.
   716		length := len(fields[0].index)
   717		tagged := -1 // Index of first tagged field.
   718		for i, f := range fields {
   719			if len(f.index) > length {
   720				fields = fields[:i]
   721				break
   722			}
   723			if f.tag {
   724				if tagged >= 0 {
   725					// Multiple tagged fields at the same level: conflict.
   726					// Return no field.
   727					return field{}, false
   728				}
   729				tagged = i
   730			}
   731		}
   732		if tagged >= 0 {
   733			return fields[tagged], true
   734		}
   735		// All remaining fields have the same length. If there's more than one,
   736		// we have a conflict (two fields named "X" at the same level) and we
   737		// return no field.
   738		if len(fields) > 1 {
   739			return field{}, false
   740		}
   741		return fields[0], true
   742	}
   743	
   744	var fieldCache struct {
   745		sync.RWMutex
   746		m map[reflect.Type][]field
   747	}
   748	
   749	// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
   750	func cachedTypeFields(t reflect.Type) []field {
   751		fieldCache.RLock()
   752		f := fieldCache.m[t]
   753		fieldCache.RUnlock()
   754		if f != nil {
   755			return f
   756		}
   757	
   758		// Compute fields without lock.
   759		// Might duplicate effort but won't hold other computations back.
   760		f = typeFields(t)
   761		if f == nil {
   762			f = []field{}
   763		}
   764	
   765		fieldCache.Lock()
   766		if fieldCache.m == nil {
   767			fieldCache.m = map[reflect.Type][]field{}
   768		}
   769		fieldCache.m[t] = f
   770		fieldCache.Unlock()
   771		return f
   772	}

View as plain text