// object consumes an object from d.data[d.off-1:], decoding into the value v. // the first byte of the object ('{') has been read already. func (d *decodeState) object(v reflect.Value) { // Check for unmarshaler. unmarshaler, pv := d.indirect(v, false) if unmarshaler != nil { d.off-- err := unmarshaler.UnmarshalJSON(d.next()) if err != nil { d.error(err) } return } v = pv // Decoding into nil interface? Switch to non-reflect code. iv, ok := v.(*reflect.InterfaceValue) if ok { iv.Set(reflect.NewValue(d.objectInterface())) return } // Check type of target: struct or map[string]T var ( mv *reflect.MapValue sv *reflect.StructValue ) switch v := v.(type) { case *reflect.MapValue: // map must have string type t := v.Type().(*reflect.MapType) if t.Key() != reflect.Typeof("") { d.saveError(&UnmarshalTypeError{"object", v.Type()}) break } mv = v if mv.IsNil() { mv.SetValue(reflect.MakeMap(t)) } case *reflect.StructValue: sv = v default: d.saveError(&UnmarshalTypeError{"object", v.Type()}) } if mv == nil && sv == nil { d.off-- d.next() // skip over { } in input return } for { // Read opening " of string key or closing }. op := d.scanWhile(scanSkipSpace) if op == scanEndObject { // closing } - can only happen on first iteration. break } if op != scanBeginLiteral { d.error(errPhase) } // Read string key. start := d.off - 1 op = d.scanWhile(scanContinue) item := d.data[start : d.off-1] key, ok := unquote(item) if !ok { d.error(errPhase) } // Figure out field corresponding to key. var subv reflect.Value if mv != nil { subv = reflect.MakeZero(mv.Type().(*reflect.MapType).Elem()) } else { // First try for field with that tag. for i := 0; i < sv.NumField(); i++ { f := sv.Type().(*reflect.StructType).Field(i) if f.Tag == key { subv = sv.Field(i) break } } if subv == nil { // Second, exact match. subv = sv.FieldByName(key) if subv == nil { // Third, case-insensitive match. subv = sv.FieldByNameFunc(func(s string) bool { return matchName(key, s) }) } } } // Read : before value. if op == scanSkipSpace { op = d.scanWhile(scanSkipSpace) } if op != scanObjectKey { d.error(errPhase) } // Read value. d.value(subv) // Write value back to map; // if using struct, subv points into struct already. if mv != nil { mv.SetElem(reflect.NewValue(key), subv) } // Next token must be , or }. op = d.scanWhile(scanSkipSpace) if op == scanEndObject { break } if op != scanObjectValue { d.error(errPhase) } } }