13 cmn "github.com/tendermint/tmlibs/common"
16 type TypeInfo struct {
17 Type reflect.Type // The type
19 // If Type is kind reflect.Interface, is registered
20 IsRegisteredInterface bool
21 ByteToType map[byte]reflect.Type
22 TypeToByte map[reflect.Type]byte
24 // If Type is kind reflect.Struct
25 Fields []StructFieldInfo
26 Unwrap bool // if struct has only one field and its an anonymous interface
30 JSONName string // (JSON) Corresponding JSON field name. (override with `json=""`)
31 JSONOmitEmpty bool // (JSON) Omit field if value is empty
32 Varint bool // (Binary) Use length-prefixed encoding for (u)int64
33 Unsafe bool // (JSON/Binary) Explicitly enable support for floats or maps
34 ZeroValue interface{} // Prototype zero object
37 func getOptionsFromField(field reflect.StructField) (skip bool, opts Options) {
38 jsonTag := field.Tag.Get("json")
39 binTag := field.Tag.Get("binary")
40 wireTag := field.Tag.Get("wire")
45 jsonTagParts := strings.Split(jsonTag, ",")
46 if jsonTagParts[0] == "" {
47 opts.JSONName = field.Name
49 opts.JSONName = jsonTagParts[0]
51 if len(jsonTagParts) > 1 {
52 if jsonTagParts[1] == "omitempty" {
53 opts.JSONOmitEmpty = true
56 if binTag == "varint" { // TODO: extend
59 if wireTag == "unsafe" {
62 opts.ZeroValue = reflect.Zero(field.Type).Interface()
66 type StructFieldInfo struct {
67 Index int // Struct field index
68 Type reflect.Type // Struct field type
69 Options // Encoding options
72 func (info StructFieldInfo) unpack() (int, reflect.Type, Options) {
73 return info.Index, info.Type, info.Options
76 // e.g. If o is struct{Foo}{}, return is the Foo reflection type.
77 func GetTypeFromStructDeclaration(o interface{}) reflect.Type {
78 rt := reflect.TypeOf(o)
79 if rt.NumField() != 1 {
80 cmn.PanicSanity("Unexpected number of fields in struct-wrapped declaration of type")
82 return rt.Field(0).Type
85 // Predeclaration of common types
87 timeType = GetTypeFromStructDeclaration(struct{ time.Time }{})
91 RFC3339Millis = "2006-01-02T15:04:05.000Z" // forced microseconds
94 // NOTE: do not access typeInfos directly, but call GetTypeInfo()
95 var typeInfosMtx sync.RWMutex
96 var typeInfos = map[reflect.Type]*TypeInfo{}
98 func GetTypeInfo(rt reflect.Type) *TypeInfo {
100 info := typeInfos[rt]
101 typeInfosMtx.RUnlock()
103 info = MakeTypeInfo(rt)
106 typeInfosMtx.Unlock()
111 // For use with the RegisterInterface declaration
112 type ConcreteType struct {
117 // This function should be used to register the receiving interface that will
118 // be used to decode an underlying concrete type. The interface MUST be embedded
119 // in a struct, and the interface MUST be the only field and it MUST be exported.
121 // RegisterInterface(struct{ Animal }{}, ConcreteType{&foo, 0x01})
122 func RegisterInterface(o interface{}, ctypes ...ConcreteType) *TypeInfo {
123 it := GetTypeFromStructDeclaration(o)
124 if it.Kind() != reflect.Interface {
125 cmn.PanicSanity("RegisterInterface expects an interface")
127 toType := make(map[byte]reflect.Type, 0)
128 toByte := make(map[reflect.Type]byte, 0)
129 for _, ctype := range ctypes {
130 crt := reflect.TypeOf(ctype.O)
131 typeByte := ctype.Byte
132 if typeByte == 0x00 {
133 cmn.PanicSanity(cmn.Fmt("Byte of 0x00 is reserved for nil (%v)", ctype))
135 if toType[typeByte] != nil {
136 cmn.PanicSanity(cmn.Fmt("Duplicate Byte for type %v and %v", ctype, toType[typeByte]))
138 toType[typeByte] = crt
139 toByte[crt] = typeByte
141 typeInfo := &TypeInfo{
143 IsRegisteredInterface: true,
147 typeInfos[it] = typeInfo
151 func MakeTypeInfo(rt reflect.Type) *TypeInfo {
152 info := &TypeInfo{Type: rt}
154 // If struct, register field name options
155 if rt.Kind() == reflect.Struct {
156 numFields := rt.NumField()
157 structFields := []StructFieldInfo{}
158 for i := 0; i < numFields; i++ {
160 if field.PkgPath != "" {
163 skip, opts := getOptionsFromField(field)
167 structFields = append(structFields, StructFieldInfo{
173 info.Fields = structFields
175 // Maybe type is a wrapper.
176 if len(structFields) == 1 {
177 jsonName := rt.Field(structFields[0].Index).Tag.Get("json")
178 if jsonName == "unwrap" {
187 // Contract: Caller must ensure that rt is supported
188 // (e.g. is recursively composed of supported native types, and structs and slices.)
189 func readReflectBinary(rv reflect.Value, rt reflect.Type, opts Options, r io.Reader, lmt int, n *int, err *error) {
192 typeInfo := GetTypeInfo(rt)
194 if rt.Kind() == reflect.Interface {
195 if !typeInfo.IsRegisteredInterface {
196 // There's no way we can read such a thing.
197 *err = errors.New(cmn.Fmt("Cannot read unregistered interface type %v", rt))
200 typeByte := ReadByte(r, n, err)
204 if typeByte == 0x00 {
207 crt, ok := typeInfo.ByteToType[typeByte]
209 *err = errors.New(cmn.Fmt("Unexpected type byte %X for type %v", typeByte, rt))
212 if crt.Kind() == reflect.Ptr {
214 crv := reflect.New(crt)
215 readReflectBinary(crv.Elem(), crt, opts, r, lmt, n, err)
216 rv.Set(crv) // NOTE: orig rv is ignored.
218 crv := reflect.New(crt).Elem()
219 readReflectBinary(crv, crt, opts, r, lmt, n, err)
220 rv.Set(crv) // NOTE: orig rv is ignored.
225 if rt.Kind() == reflect.Ptr {
226 typeByte := ReadByte(r, n, err)
230 if typeByte == 0x00 {
232 } else if typeByte != 0x01 {
233 *err = errors.New(cmn.Fmt("Unexpected type byte %X for ptr of untyped thing", typeByte))
236 // Create new if rv is nil.
238 newRv := reflect.New(rt.Elem())
242 // Dereference pointer
243 rv, rt = rv.Elem(), rt.Elem()
244 typeInfo = GetTypeInfo(rt)
252 if elemRt.Kind() == reflect.Uint8 {
253 // Special case: Bytearrays
254 buf := make([]byte, length)
255 ReadFull(buf, r, n, err)
259 //log.Info("Read bytearray", "bytes", buf, "n", *n)
260 reflect.Copy(rv, reflect.ValueOf(buf))
262 for i := 0; i < length; i++ {
263 elemRv := rv.Index(i)
264 readReflectBinary(elemRv, elemRt, opts, r, lmt, n, err)
268 if lmt != 0 && lmt < *n {
269 *err = ErrBinaryReadOverflow
273 //log.Info("Read x-array", "x", elemRt, "length", length, "n", *n)
278 if elemRt.Kind() == reflect.Uint8 {
279 // Special case: Byteslices
280 byteslice := ReadByteSlice(r, lmt, n, err)
281 //log.Info("Read byteslice", "bytes", byteslice, "n", *n)
282 rv.Set(reflect.ValueOf(byteslice))
284 var sliceRv reflect.Value
286 length := ReadVarint(r, n, err)
287 //log.Info("Read slice", "length", length, "n", *n)
288 sliceRv = reflect.MakeSlice(rt, 0, 0)
289 // read one ReadSliceChunkSize at a time and append
290 for i := 0; i*ReadSliceChunkSize < length; i++ {
291 l := cmn.MinInt(ReadSliceChunkSize, length-i*ReadSliceChunkSize)
292 tmpSliceRv := reflect.MakeSlice(rt, l, l)
293 for j := 0; j < l; j++ {
294 elemRv := tmpSliceRv.Index(j)
295 readReflectBinary(elemRv, elemRt, opts, r, lmt, n, err)
299 if lmt != 0 && lmt < *n {
300 *err = ErrBinaryReadOverflow
304 sliceRv = reflect.AppendSlice(sliceRv, tmpSliceRv)
312 // Special case: time.Time
313 t := ReadTime(r, n, err)
314 //log.Info("Read time", "t", t, "n", *n)
315 rv.Set(reflect.ValueOf(t))
317 for _, fieldInfo := range typeInfo.Fields {
318 fieldIdx, fieldType, opts := fieldInfo.unpack()
319 fieldRv := rv.Field(fieldIdx)
320 readReflectBinary(fieldRv, fieldType, opts, r, lmt, n, err)
325 str := ReadString(r, lmt, n, err)
326 //log.Info("Read string", "str", str, "n", *n)
331 num := ReadVarint(r, n, err)
332 //log.Info("Read num", "num", num, "n", *n)
333 rv.SetInt(int64(num))
335 num := ReadInt64(r, n, err)
336 //log.Info("Read num", "num", num, "n", *n)
337 rv.SetInt(int64(num))
341 num := ReadUint32(r, n, err)
342 //log.Info("Read num", "num", num, "n", *n)
343 rv.SetInt(int64(num))
346 num := ReadUint16(r, n, err)
347 //log.Info("Read num", "num", num, "n", *n)
348 rv.SetInt(int64(num))
351 num := ReadUint8(r, n, err)
352 //log.Info("Read num", "num", num, "n", *n)
353 rv.SetInt(int64(num))
356 num := ReadVarint(r, n, err)
357 //log.Info("Read num", "num", num, "n", *n)
358 rv.SetInt(int64(num))
362 num := ReadVarint(r, n, err)
363 //log.Info("Read num", "num", num, "n", *n)
364 rv.SetUint(uint64(num))
366 num := ReadUint64(r, n, err)
367 //log.Info("Read num", "num", num, "n", *n)
368 rv.SetUint(uint64(num))
372 num := ReadUint32(r, n, err)
373 //log.Info("Read num", "num", num, "n", *n)
374 rv.SetUint(uint64(num))
377 num := ReadUint16(r, n, err)
378 //log.Info("Read num", "num", num, "n", *n)
379 rv.SetUint(uint64(num))
382 num := ReadUint8(r, n, err)
383 //log.Info("Read num", "num", num, "n", *n)
384 rv.SetUint(uint64(num))
387 num := ReadVarint(r, n, err)
388 //log.Info("Read num", "num", num, "n", *n)
389 rv.SetUint(uint64(num))
392 num := ReadUint8(r, n, err)
393 //log.Info("Read bool", "bool", num, "n", *n)
396 case reflect.Float64:
398 *err = errors.New("Wire float* support requires `wire:\"unsafe\"`")
401 num := ReadFloat64(r, n, err)
402 //log.Info("Read num", "num", num, "n", *n)
403 rv.SetFloat(float64(num))
405 case reflect.Float32:
407 *err = errors.New("Wire float* support requires `wire:\"unsafe\"`")
410 num := ReadFloat32(r, n, err)
411 //log.Info("Read num", "num", num, "n", *n)
412 rv.SetFloat(float64(num))
415 cmn.PanicSanity(cmn.Fmt("Unknown field type %v", rt.Kind()))
419 // rv: the reflection value of the thing to write
420 // rt: the type of rv as declared in the container, not necessarily rv.Type().
421 func writeReflectBinary(rv reflect.Value, rt reflect.Type, opts Options, w io.Writer, n *int, err *error) {
424 typeInfo := GetTypeInfo(rt)
426 if rt.Kind() == reflect.Interface {
428 WriteByte(0x00, w, n, err)
431 crv := rv.Elem() // concrete reflection value
432 crt := crv.Type() // concrete reflection type
433 if typeInfo.IsRegisteredInterface {
434 // See if the crt is registered.
435 // If so, we're more restrictive.
436 typeByte, ok := typeInfo.TypeToByte[crt]
440 *err = errors.New(cmn.Fmt("Unexpected pointer type %v for registered interface %v. "+
441 "Was it registered as a value receiver rather than as a pointer receiver?", crt, rt.Name()))
443 *err = errors.New(cmn.Fmt("Unexpected struct type %v for registered interface %v. "+
444 "Was it registered as a pointer receiver rather than as a value receiver?", crt, rt.Name()))
446 *err = errors.New(cmn.Fmt("Unexpected type %v for registered interface %v. "+
447 "If this is intentional, please register it.", crt, rt.Name()))
451 if crt.Kind() == reflect.Ptr {
452 crv, crt = crv.Elem(), crt.Elem()
454 *err = errors.New(cmn.Fmt("Unexpected nil-pointer of type %v for registered interface %v. "+
455 "For compatibility with other languages, nil-pointer interface values are forbidden.", crt, rt.Name()))
459 WriteByte(typeByte, w, n, err)
460 writeReflectBinary(crv, crt, opts, w, n, err)
462 // We support writing unregistered interfaces for convenience.
463 writeReflectBinary(crv, crt, opts, w, n, err)
468 if rt.Kind() == reflect.Ptr {
469 // Dereference pointer
470 rv, rt = rv.Elem(), rt.Elem()
471 typeInfo = GetTypeInfo(rt)
473 WriteByte(0x00, w, n, err)
476 WriteByte(0x01, w, n, err)
486 if elemRt.Kind() == reflect.Uint8 {
487 // Special case: Bytearrays
489 byteslice := rv.Slice(0, length).Bytes()
490 WriteTo(byteslice, w, n, err)
493 buf := make([]byte, length)
494 reflect.Copy(reflect.ValueOf(buf), rv) // XXX: looks expensive!
495 WriteTo(buf, w, n, err)
499 for i := 0; i < length; i++ {
500 elemRv := rv.Index(i)
501 writeReflectBinary(elemRv, elemRt, opts, w, n, err)
507 if elemRt.Kind() == reflect.Uint8 {
508 // Special case: Byteslices
509 byteslice := rv.Bytes()
510 WriteByteSlice(byteslice, w, n, err)
514 WriteVarint(length, w, n, err)
516 for i := 0; i < length; i++ {
517 elemRv := rv.Index(i)
518 writeReflectBinary(elemRv, elemRt, opts, w, n, err)
524 // Special case: time.Time
525 WriteTime(rv.Interface().(time.Time), w, n, err)
527 for _, fieldInfo := range typeInfo.Fields {
528 fieldIdx, fieldType, opts := fieldInfo.unpack()
529 fieldRv := rv.Field(fieldIdx)
530 writeReflectBinary(fieldRv, fieldType, opts, w, n, err)
535 WriteString(rv.String(), w, n, err)
539 WriteVarint(int(rv.Int()), w, n, err)
541 WriteInt64(rv.Int(), w, n, err)
545 WriteInt32(int32(rv.Int()), w, n, err)
548 WriteInt16(int16(rv.Int()), w, n, err)
551 WriteInt8(int8(rv.Int()), w, n, err)
554 WriteVarint(int(rv.Int()), w, n, err)
558 WriteUvarint(uint(rv.Uint()), w, n, err)
560 WriteUint64(rv.Uint(), w, n, err)
564 WriteUint32(uint32(rv.Uint()), w, n, err)
567 WriteUint16(uint16(rv.Uint()), w, n, err)
570 WriteUint8(uint8(rv.Uint()), w, n, err)
573 WriteUvarint(uint(rv.Uint()), w, n, err)
577 WriteUint8(uint8(1), w, n, err)
579 WriteUint8(uint8(0), w, n, err)
582 case reflect.Float64:
584 *err = errors.New("Wire float* support requires `wire:\"unsafe\"`")
587 WriteFloat64(rv.Float(), w, n, err)
589 case reflect.Float32:
591 *err = errors.New("Wire float* support requires `wire:\"unsafe\"`")
594 WriteFloat32(float32(rv.Float()), w, n, err)
597 cmn.PanicSanity(cmn.Fmt("Unknown field type %v", rt.Kind()))
601 //-----------------------------------------------------------------------------
603 func readByteJSON(o interface{}) (typeByte byte, rest interface{}, err error) {
604 oSlice, ok := o.([]interface{})
606 err = errors.New(cmn.Fmt("Expected type [Byte,?] but got type %v", reflect.TypeOf(o)))
609 if len(oSlice) != 2 {
610 err = errors.New(cmn.Fmt("Expected [Byte,?] len 2 but got len %v", len(oSlice)))
613 typeByte_, ok := oSlice[0].(float64)
614 typeByte = byte(typeByte_)
619 // Contract: Caller must ensure that rt is supported
620 // (e.g. is recursively composed of supported native types, and structs and slices.)
621 // rv and rt refer to the object we're unmarhsaling into, whereas o is the result of naiive json unmarshal (map[string]interface{})
622 func readReflectJSON(rv reflect.Value, rt reflect.Type, opts Options, o interface{}, err *error) {
625 typeInfo := GetTypeInfo(rt)
627 if rt.Kind() == reflect.Interface {
628 if !typeInfo.IsRegisteredInterface {
629 // There's no way we can read such a thing.
630 *err = errors.New(cmn.Fmt("Cannot read unregistered interface type %v", rt))
636 typeByte, rest, err_ := readByteJSON(o)
641 crt, ok := typeInfo.ByteToType[typeByte]
643 *err = errors.New(cmn.Fmt("Byte %X not registered for interface %v", typeByte, rt))
646 if crt.Kind() == reflect.Ptr {
648 crv := reflect.New(crt)
649 readReflectJSON(crv.Elem(), crt, opts, rest, err)
650 rv.Set(crv) // NOTE: orig rv is ignored.
652 crv := reflect.New(crt).Elem()
653 readReflectJSON(crv, crt, opts, rest, err)
654 rv.Set(crv) // NOTE: orig rv is ignored.
659 if rt.Kind() == reflect.Ptr {
663 // Create new struct if rv is nil.
665 newRv := reflect.New(rt.Elem())
669 // Dereference pointer
670 rv, rt = rv.Elem(), rt.Elem()
671 typeInfo = GetTypeInfo(rt)
679 if elemRt.Kind() == reflect.Uint8 {
680 // Special case: Bytearrays
681 oString, ok := o.(string)
683 *err = errors.New(cmn.Fmt("Expected string but got type %v", reflect.TypeOf(o)))
686 buf, err_ := hex.DecodeString(oString)
691 if len(buf) != length {
692 *err = errors.New(cmn.Fmt("Expected bytearray of length %v but got %v", length, len(buf)))
695 //log.Info("Read bytearray", "bytes", buf)
696 reflect.Copy(rv, reflect.ValueOf(buf))
698 oSlice, ok := o.([]interface{})
700 *err = errors.New(cmn.Fmt("Expected array of %v but got type %v", rt, reflect.TypeOf(o)))
703 if len(oSlice) != length {
704 *err = errors.New(cmn.Fmt("Expected array of length %v but got %v", length, len(oSlice)))
707 for i := 0; i < length; i++ {
708 elemRv := rv.Index(i)
709 readReflectJSON(elemRv, elemRt, opts, oSlice[i], err)
711 //log.Info("Read x-array", "x", elemRt, "length", length)
716 if elemRt.Kind() == reflect.Uint8 {
717 // Special case: Byteslices
718 oString, ok := o.(string)
720 *err = errors.New(cmn.Fmt("Expected string but got type %v", reflect.TypeOf(o)))
723 byteslice, err_ := hex.DecodeString(oString)
728 //log.Info("Read byteslice", "bytes", byteslice)
729 rv.Set(reflect.ValueOf(byteslice))
732 oSlice, ok := o.([]interface{})
734 *err = errors.New(cmn.Fmt("Expected array of %v but got type %v", rt, reflect.TypeOf(o)))
737 length := len(oSlice)
738 //log.Info("Read slice", "length", length)
739 sliceRv := reflect.MakeSlice(rt, length, length)
741 for i := 0; i < length; i++ {
742 elemRv := sliceRv.Index(i)
743 readReflectJSON(elemRv, elemRt, opts, oSlice[i], err)
750 // Special case: time.Time
751 str, ok := o.(string)
753 *err = errors.New(cmn.Fmt("Expected string but got type %v", reflect.TypeOf(o)))
756 // try three ways, seconds, milliseconds, or microseconds...
757 t, err_ := time.Parse(time.RFC3339Nano, str)
762 rv.Set(reflect.ValueOf(t))
765 fieldIdx, fieldType, opts := typeInfo.Fields[0].unpack()
766 fieldRv := rv.Field(fieldIdx)
767 readReflectJSON(fieldRv, fieldType, opts, o, err)
769 oMap, ok := o.(map[string]interface{})
771 *err = errors.New(cmn.Fmt("Expected map but got type %v", reflect.TypeOf(o)))
774 // TODO: ensure that all fields are set?
775 // TODO: disallow unknown oMap fields?
776 for _, fieldInfo := range typeInfo.Fields {
777 fieldIdx, fieldType, opts := fieldInfo.unpack()
778 value, ok := oMap[opts.JSONName]
780 continue // Skip missing fields.
782 fieldRv := rv.Field(fieldIdx)
783 readReflectJSON(fieldRv, fieldType, opts, value, err)
789 str, ok := o.(string)
791 *err = errors.New(cmn.Fmt("Expected string but got type %v", reflect.TypeOf(o)))
794 //log.Info("Read string", "str", str)
797 case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
798 num, ok := o.(float64)
800 *err = errors.New(cmn.Fmt("Expected numeric but got type %v", reflect.TypeOf(o)))
803 //log.Info("Read num", "num", num)
804 rv.SetInt(int64(num))
806 case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint:
807 num, ok := o.(float64)
809 *err = errors.New(cmn.Fmt("Expected numeric but got type %v", reflect.TypeOf(o)))
813 *err = errors.New(cmn.Fmt("Expected unsigned numeric but got %v", num))
816 //log.Info("Read num", "num", num)
817 rv.SetUint(uint64(num))
819 case reflect.Float64, reflect.Float32:
821 *err = errors.New("Wire float* support requires `wire:\"unsafe\"`")
824 num, ok := o.(float64)
826 *err = errors.New(cmn.Fmt("Expected numeric but got type %v", reflect.TypeOf(o)))
829 //log.Info("Read num", "num", num)
835 *err = errors.New(cmn.Fmt("Expected boolean but got type %v", reflect.TypeOf(o)))
838 //log.Info("Read boolean", "boolean", bl)
842 cmn.PanicSanity(cmn.Fmt("Unknown field type %v", rt.Kind()))
846 func writeReflectJSON(rv reflect.Value, rt reflect.Type, opts Options, w io.Writer, n *int, err *error) {
847 //log.Info(cmn.Fmt("writeReflectJSON(%v, %v, %v, %v, %v)", rv, rt, w, n, err))
850 typeInfo := GetTypeInfo(rt)
852 if rt.Kind() == reflect.Interface {
854 WriteTo([]byte("null"), w, n, err)
857 crv := rv.Elem() // concrete reflection value
858 crt := crv.Type() // concrete reflection type
859 if typeInfo.IsRegisteredInterface {
860 // See if the crt is registered.
861 // If so, we're more restrictive.
862 typeByte, ok := typeInfo.TypeToByte[crt]
866 *err = errors.New(cmn.Fmt("Unexpected pointer type %v for registered interface %v. "+
867 "Was it registered as a value receiver rather than as a pointer receiver?", crt, rt.Name()))
869 *err = errors.New(cmn.Fmt("Unexpected struct type %v for registered interface %v. "+
870 "Was it registered as a pointer receiver rather than as a value receiver?", crt, rt.Name()))
872 *err = errors.New(cmn.Fmt("Unexpected type %v for registered interface %v. "+
873 "If this is intentional, please register it.", crt, rt.Name()))
877 if crt.Kind() == reflect.Ptr {
878 crv, crt = crv.Elem(), crt.Elem()
880 *err = errors.New(cmn.Fmt("Unexpected nil-pointer of type %v for registered interface %v. "+
881 "For compatibility with other languages, nil-pointer interface values are forbidden.", crt, rt.Name()))
885 WriteTo([]byte(cmn.Fmt("[%v,", typeByte)), w, n, err)
886 writeReflectJSON(crv, crt, opts, w, n, err)
887 WriteTo([]byte("]"), w, n, err)
889 // We support writing unregistered interfaces for convenience.
890 writeReflectJSON(crv, crt, opts, w, n, err)
895 if rt.Kind() == reflect.Ptr {
896 // Dereference pointer
897 rv, rt = rv.Elem(), rt.Elem()
898 typeInfo = GetTypeInfo(rt)
900 // For better compatibility with other languages,
901 // as far as tendermint/wire is concerned,
902 // pointers to nil values are the same as nil.
903 WriteTo([]byte("null"), w, n, err)
914 if elemRt.Kind() == reflect.Uint8 {
915 // Special case: Bytearray
916 bytearray := reflect.ValueOf(make([]byte, length))
917 reflect.Copy(bytearray, rv)
918 WriteTo([]byte(cmn.Fmt("\"%X\"", bytearray.Interface())), w, n, err)
920 WriteTo([]byte("["), w, n, err)
922 for i := 0; i < length; i++ {
923 elemRv := rv.Index(i)
924 writeReflectJSON(elemRv, elemRt, opts, w, n, err)
926 WriteTo([]byte(","), w, n, err)
929 WriteTo([]byte("]"), w, n, err)
934 if elemRt.Kind() == reflect.Uint8 {
935 // Special case: Byteslices
936 byteslice := rv.Bytes()
937 WriteTo([]byte(cmn.Fmt("\"%X\"", byteslice)), w, n, err)
939 WriteTo([]byte("["), w, n, err)
942 for i := 0; i < length; i++ {
943 elemRv := rv.Index(i)
944 writeReflectJSON(elemRv, elemRt, opts, w, n, err)
946 WriteTo([]byte(","), w, n, err)
949 WriteTo([]byte("]"), w, n, err)
954 // Special case: time.Time
955 t := rv.Interface().(time.Time).UTC()
956 str := t.Format(RFC3339Millis)
957 jsonBytes, err_ := json.Marshal(str)
962 WriteTo(jsonBytes, w, n, err)
965 fieldIdx, fieldType, opts := typeInfo.Fields[0].unpack()
966 fieldRv := rv.Field(fieldIdx)
967 writeReflectJSON(fieldRv, fieldType, opts, w, n, err)
969 WriteTo([]byte("{"), w, n, err)
971 for _, fieldInfo := range typeInfo.Fields {
972 fieldIdx, fieldType, opts := fieldInfo.unpack()
973 fieldRv := rv.Field(fieldIdx)
974 if opts.JSONOmitEmpty && isEmpty(fieldType, fieldRv, opts) { // Skip zero value if omitempty
978 WriteTo([]byte(","), w, n, err)
982 WriteTo([]byte(cmn.Fmt("\"%v\":", opts.JSONName)), w, n, err)
983 writeReflectJSON(fieldRv, fieldType, opts, w, n, err)
985 WriteTo([]byte("}"), w, n, err)
991 case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint:
993 case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
996 jsonBytes, err_ := json.Marshal(rv.Interface())
1001 WriteTo(jsonBytes, w, n, err)
1003 case reflect.Float64, reflect.Float32:
1005 *err = errors.New("Wire float* support requires `wire:\"unsafe\"`")
1008 jsonBytes, err_ := json.Marshal(rv.Interface())
1013 WriteTo(jsonBytes, w, n, err)
1016 cmn.PanicSanity(cmn.Fmt("Unknown field type %v", rt.Kind()))
1021 func isEmpty(rt reflect.Type, rv reflect.Value, opts Options) bool {
1022 if rt.Comparable() {
1023 // if its comparable we can check directly
1024 if rv.Interface() == opts.ZeroValue {
1029 // TODO: A faster alternative might be to call writeReflectJSON
1030 // onto a buffer and check if its "{}" or not.
1032 case reflect.Struct:
1034 typeInfo := GetTypeInfo(rt)
1035 for _, fieldInfo := range typeInfo.Fields {
1036 fieldIdx, fieldType, opts := fieldInfo.unpack()
1037 fieldRv := rv.Field(fieldIdx)
1038 if !isEmpty(fieldType, fieldRv, opts) { // Skip zero value if omitempty