func (e *encodeState) reflectValue(v reflect.Value) { if v == nil { e.WriteString("null") return } if j, ok := v.Interface().(Marshaler); ok { b, err := j.MarshalXML() if err == nil { // copy XML into buffer, checking validity. err = Compact(&e.Buffer, b) } if err != nil { e.error(&MarshalerError{v.Type(), err}) } return } switch v := v.(type) { case *reflect.BoolValue: x := v.Get() if x { e.WriteString("true") } else { e.WriteString("false") } case *reflect.IntValue: e.WriteString(strconv.Itoa64(v.Get())) case *reflect.UintValue: e.WriteString(strconv.Uitoa64(v.Get())) case *reflect.FloatValue: e.WriteString(strconv.FtoaN(v.Get(), 'g', -1, v.Type().Bits())) case *reflect.StringValue: e.WriteString(v.Get()) case *reflect.StructValue: t := v.Type().(*reflect.StructType) e.openTag(t.Name()) n := v.NumField() for i := 0; i < n; i++ { f := t.Field(i) if f.Tag != "" { e.openTag(f.Tag) e.reflectValue(v.Field(i)) e.closeTag(f.Tag) } else { e.openTag(f.Name) e.reflectValue(v.Field(i)) e.closeTag(f.Name) } } e.closeTag(t.Name()) case *reflect.MapValue: if _, ok := v.Type().(*reflect.MapType).Key().(*reflect.StringType); !ok { e.error(&UnsupportedTypeError{v.Type()}) } if v.IsNil() { e.WriteString("null") break } e.WriteByte('{') var sv stringValues = v.Keys() sort.Sort(sv) for i, k := range sv { if i > 0 { e.WriteByte(',') } e.string(k.(*reflect.StringValue).Get()) e.WriteByte(':') e.reflectValue(v.Elem(k)) } e.WriteByte('}') case reflect.ArrayOrSliceValue: e.WriteByte('[') n := v.Len() for i := 0; i < n; i++ { if i > 0 { e.WriteByte(',') } e.reflectValue(v.Elem(i)) } e.WriteByte(']') case interfaceOrPtrValue: if v.IsNil() { e.WriteString("null") return } e.reflectValue(v.Elem()) default: e.error(&UnsupportedTypeError{v.Type()}) } return }
func (e *encodeState) reflectValue(v reflect.Value) { if v == nil { e.WriteString("null") return } if j, ok := v.Interface().(Marshaler); ok { b, err := j.MarshalJSON() if err == nil { // copy JSON into buffer, checking validity. err = Compact(&e.Buffer, b) } if err != nil { e.error(&MarshalerError{v.Type(), err}) } return } switch v := v.(type) { case *reflect.BoolValue: x := v.Get() if x { e.WriteString("true") } else { e.WriteString("false") } case *reflect.IntValue: e.WriteString(strconv.Itoa64(v.Get())) case *reflect.UintValue: e.WriteString(strconv.Uitoa64(v.Get())) case *reflect.FloatValue: e.WriteString(strconv.FtoaN(v.Get(), 'g', -1, v.Type().Bits())) case *reflect.StringValue: e.string(v.Get()) case *reflect.StructValue: e.WriteByte('{') t := v.Type().(*reflect.StructType) n := v.NumField() first := true for i := 0; i < n; i++ { f := t.Field(i) if f.PkgPath != "" { continue } if first { first = false } else { e.WriteByte(',') } if isValidTag(f.Tag) { e.string(f.Tag) } else { e.string(f.Name) } e.WriteByte(':') e.reflectValue(v.Field(i)) } e.WriteByte('}') case *reflect.MapValue: if _, ok := v.Type().(*reflect.MapType).Key().(*reflect.StringType); !ok { e.error(&UnsupportedTypeError{v.Type()}) } if v.IsNil() { e.WriteString("null") break } e.WriteByte('{') var sv stringValues = v.Keys() sort.Sort(sv) for i, k := range sv { if i > 0 { e.WriteByte(',') } e.string(k.(*reflect.StringValue).Get()) e.WriteByte(':') e.reflectValue(v.Elem(k)) } e.WriteByte('}') case reflect.ArrayOrSliceValue: if v.Type() == byteSliceType { e.WriteByte('"') s := v.Interface().([]byte) if len(s) < 1024 { // for small buffers, using Encode directly is much faster. dst := make([]byte, base64.StdEncoding.EncodedLen(len(s))) base64.StdEncoding.Encode(dst, s) e.Write(dst) } else { // for large buffers, avoid unnecessary extra temporary // buffer space. enc := base64.NewEncoder(base64.StdEncoding, e) enc.Write(s) enc.Close() } e.WriteByte('"') break } e.WriteByte('[') n := v.Len() for i := 0; i < n; i++ { if i > 0 { e.WriteByte(',') } e.reflectValue(v.Elem(i)) } e.WriteByte(']') case interfaceOrPtrValue: if v.IsNil() { e.WriteString("null") return } e.reflectValue(v.Elem()) default: e.error(&UnsupportedTypeError{v.Type()}) } return }