func (e *encodeState) writeMap(v *reflect.MapValue) { if v.IsNil() { return } if _, ok := v.Type().(*reflect.MapType).Key().(*reflect.StringType); !ok { e.abort(&EncodeTypeError{v.Type()}) } offset := e.beginDoc() for _, k := range v.Keys() { e.encodeValue(k.(*reflect.StringValue).Get(), v.Elem(k)) } e.WriteByte(0) e.endDoc(offset) }
// 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) } } }