1 // Copyright 2013 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.
18 // indirect walks down v allocating pointers as needed,
19 // until it gets to a non-pointer.
20 // if it encounters an Unmarshaler, indirect stops and returns that.
21 // if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
22 func indirect(v reflect.Value, decodingNull bool) (json.Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
23 // If v is a named type and is addressable,
24 // start with its address, so that if the type has pointer methods,
26 if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
30 // Load value from interface, but only if the result will be
31 // usefully addressable.
32 if v.Kind() == reflect.Interface && !v.IsNil() {
34 if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
40 if v.Kind() != reflect.Ptr {
44 if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
49 v.Set(reflect.New(v.Type().Elem()))
51 v = reflect.New(v.Type().Elem())
54 if v.Type().NumMethod() > 0 {
55 if u, ok := v.Interface().(json.Unmarshaler); ok {
56 return u, nil, reflect.Value{}
58 if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
59 return nil, u, reflect.Value{}
67 // A field represents a single field found in a struct.
70 nameBytes []byte // []byte(name)
71 equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent
80 func fillField(f field) field {
81 f.nameBytes = []byte(f.name)
82 f.equalFold = foldFunc(f.nameBytes)
86 // byName sorts field by name, breaking ties with depth,
87 // then breaking ties with "name came from json tag", then
88 // breaking ties with index sequence.
91 func (x byName) Len() int { return len(x) }
93 func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
95 func (x byName) Less(i, j int) bool {
96 if x[i].name != x[j].name {
97 return x[i].name < x[j].name
99 if len(x[i].index) != len(x[j].index) {
100 return len(x[i].index) < len(x[j].index)
102 if x[i].tag != x[j].tag {
105 return byIndex(x).Less(i, j)
108 // byIndex sorts field by index sequence.
111 func (x byIndex) Len() int { return len(x) }
113 func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
115 func (x byIndex) Less(i, j int) bool {
116 for k, xik := range x[i].index {
117 if k >= len(x[j].index) {
120 if xik != x[j].index[k] {
121 return xik < x[j].index[k]
124 return len(x[i].index) < len(x[j].index)
127 // typeFields returns a list of fields that JSON should recognize for the given type.
128 // The algorithm is breadth-first search over the set of structs to include - the top struct
129 // and then any reachable anonymous structs.
130 func typeFields(t reflect.Type) []field {
131 // Anonymous fields to explore at the current level and the next.
133 next := []field{{typ: t}}
135 // Count of queued names for current level and the next.
136 count := map[reflect.Type]int{}
137 nextCount := map[reflect.Type]int{}
139 // Types already visited at an earlier level.
140 visited := map[reflect.Type]bool{}
146 current, next = next, current[:0]
147 count, nextCount = nextCount, map[reflect.Type]int{}
149 for _, f := range current {
153 visited[f.typ] = true
155 // Scan f.typ for fields to include.
156 for i := 0; i < f.typ.NumField(); i++ {
158 if sf.PkgPath != "" { // unexported
161 tag := sf.Tag.Get("json")
165 name, opts := parseTag(tag)
166 if !isValidTag(name) {
169 index := make([]int, len(f.index)+1)
171 index[len(f.index)] = i
174 if ft.Name() == "" && ft.Kind() == reflect.Ptr {
179 // Record found field and index sequence.
180 if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
185 fields = append(fields, fillField(field{
190 omitEmpty: opts.Contains("omitempty"),
191 quoted: opts.Contains("string"),
193 if count[f.typ] > 1 {
194 // If there were multiple instances, add a second,
195 // so that the annihilation code will see a duplicate.
196 // It only cares about the distinction between 1 or 2,
197 // so don't bother generating any more copies.
198 fields = append(fields, fields[len(fields)-1])
203 // Record new anonymous struct to explore in next round.
205 if nextCount[ft] == 1 {
206 next = append(next, fillField(field{name: ft.Name(), index: index, typ: ft}))
212 sort.Sort(byName(fields))
214 // Delete all fields that are hidden by the Go rules for embedded fields,
215 // except that fields with JSON tags are promoted.
217 // The fields are sorted in primary order of name, secondary order
218 // of field index length. Loop over names; for each name, delete
219 // hidden fields by choosing the one dominant field that survives.
221 for advance, i := 0, 0; i < len(fields); i += advance {
222 // One iteration per name.
223 // Find the sequence of fields with the name of this first field.
226 for advance = 1; i+advance < len(fields); advance++ {
227 fj := fields[i+advance]
232 if advance == 1 { // Only one field with this name
233 out = append(out, fi)
236 dominant, ok := dominantField(fields[i : i+advance])
238 out = append(out, dominant)
243 sort.Sort(byIndex(fields))
248 // dominantField looks through the fields, all of which are known to
249 // have the same name, to find the single field that dominates the
250 // others using Go's embedding rules, modified by the presence of
251 // JSON tags. If there are multiple top-level fields, the boolean
252 // will be false: This condition is an error in Go and we skip all
254 func dominantField(fields []field) (field, bool) {
255 // The fields are sorted in increasing index-length order. The winner
256 // must therefore be one with the shortest index length. Drop all
257 // longer entries, which is easy: just truncate the slice.
258 length := len(fields[0].index)
259 tagged := -1 // Index of first tagged field.
260 for i, f := range fields {
261 if len(f.index) > length {
267 // Multiple tagged fields at the same level: conflict.
269 return field{}, false
275 return fields[tagged], true
277 // All remaining fields have the same length. If there's more than one,
278 // we have a conflict (two fields named "X" at the same level) and we
281 return field{}, false
283 return fields[0], true
286 var fieldCache struct {
288 m map[reflect.Type][]field
291 // cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
292 func cachedTypeFields(t reflect.Type) []field {
300 // Compute fields without lock.
301 // Might duplicate effort but won't hold other computations back.
308 if fieldCache.m == nil {
309 fieldCache.m = map[reflect.Type][]field{}
316 func isValidTag(s string) bool {
320 for _, c := range s {
322 case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
323 // Backslash and quote chars are reserved, but
324 // otherwise any punctuation chars are allowed
327 if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
336 caseMask = ^byte(0x20) // Mask to ignore case in ASCII.
338 smallLongEss = '\u017f'
341 // foldFunc returns one of four different case folding equivalence
342 // functions, from most general (and slow) to fastest:
344 // 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
345 // 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
346 // 3) asciiEqualFold, no special, but includes non-letters (including _)
347 // 4) simpleLetterEqualFold, no specials, no non-letters.
349 // The letters S and K are special because they map to 3 runes, not just 2:
350 // * S maps to s and to U+017F 'ſ' Latin small letter long s
351 // * k maps to K and to U+212A 'K' Kelvin sign
352 // See http://play.golang.org/p/tTxjOc0OGo
354 // The returned function is specialized for matching against s and
355 // should only be given s. It's not curried for performance reasons.
356 func foldFunc(s []byte) func(s, t []byte) bool {
358 special := false // special letter
359 for _, b := range s {
360 if b >= utf8.RuneSelf {
361 return bytes.EqualFold
363 upper := b & caseMask
364 if upper < 'A' || upper > 'Z' {
366 } else if upper == 'K' || upper == 'S' {
367 // See above for why these letters are special.
372 return equalFoldRight
375 return asciiEqualFold
377 return simpleLetterEqualFold
380 // equalFoldRight is a specialization of bytes.EqualFold when s is
381 // known to be all ASCII (including punctuation), but contains an 's',
382 // 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
383 // See comments on foldFunc.
384 func equalFoldRight(s, t []byte) bool {
385 for _, sb := range s {
390 if tb < utf8.RuneSelf {
392 sbUpper := sb & caseMask
393 if 'A' <= sbUpper && sbUpper <= 'Z' {
394 if sbUpper != tb&caseMask {
404 // sb is ASCII and t is not. t must be either kelvin
405 // sign or long s; sb must be s, S, k, or K.
406 tr, size := utf8.DecodeRune(t)
409 if tr != smallLongEss {
428 // asciiEqualFold is a specialization of bytes.EqualFold for use when
429 // s is all ASCII (but may contain non-letters) and contains no
430 // special-folding letters.
431 // See comments on foldFunc.
432 func asciiEqualFold(s, t []byte) bool {
433 if len(s) != len(t) {
436 for i, sb := range s {
441 if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
442 if sb&caseMask != tb&caseMask {
452 // simpleLetterEqualFold is a specialization of bytes.EqualFold for
453 // use when s is all ASCII letters (no underscores, etc) and also
454 // doesn't contain 'k', 'K', 's', or 'S'.
455 // See comments on foldFunc.
456 func simpleLetterEqualFold(s, t []byte) bool {
457 if len(s) != len(t) {
460 for i, b := range s {
461 if b&caseMask != t[i]&caseMask {
468 // tagOptions is the string following a comma in a struct field's "json"
469 // tag, or the empty string. It does not include the leading comma.
470 type tagOptions string
472 // parseTag splits a struct field's json tag into its name and
473 // comma-separated options.
474 func parseTag(tag string) (string, tagOptions) {
475 if idx := strings.Index(tag, ","); idx != -1 {
476 return tag[:idx], tagOptions(tag[idx+1:])
478 return tag, tagOptions("")
481 // Contains reports whether a comma-separated list of options
482 // contains a particular substr flag. substr must be surrounded by a
483 // string boundary or commas.
484 func (o tagOptions) Contains(optionName string) bool {
491 i := strings.Index(s, ",")
493 s, next = s[:i], s[i+1:]