feature_reflect_map.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package jsoniter
  2. import (
  3. "encoding"
  4. "encoding/json"
  5. "reflect"
  6. "strconv"
  7. "unsafe"
  8. )
  9. type mapDecoder struct {
  10. mapType reflect.Type
  11. keyType reflect.Type
  12. elemType reflect.Type
  13. elemDecoder Decoder
  14. mapInterface emptyInterface
  15. }
  16. func (decoder *mapDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
  17. // dark magic to cast unsafe.Pointer back to interface{} using reflect.Type
  18. mapInterface := decoder.mapInterface
  19. mapInterface.word = ptr
  20. realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
  21. realVal := reflect.ValueOf(*realInterface).Elem()
  22. if realVal.IsNil() {
  23. realVal.Set(reflect.MakeMap(realVal.Type()))
  24. }
  25. iter.ReadMapCB(func(iter *Iterator, keyStr string) bool {
  26. elem := reflect.New(decoder.elemType)
  27. decoder.elemDecoder.decode(unsafe.Pointer(elem.Pointer()), iter)
  28. // to put into map, we have to use reflection
  29. keyType := decoder.keyType
  30. switch {
  31. case keyType.Kind() == reflect.String:
  32. realVal.SetMapIndex(reflect.ValueOf(keyStr), elem.Elem())
  33. return true
  34. case keyType.Implements(textUnmarshalerType):
  35. textUnmarshaler := reflect.New(keyType.Elem()).Interface().(encoding.TextUnmarshaler)
  36. err := textUnmarshaler.UnmarshalText([]byte(keyStr))
  37. if err != nil {
  38. iter.reportError("read map key as TextUnmarshaler", err.Error())
  39. return false
  40. }
  41. realVal.SetMapIndex(reflect.ValueOf(textUnmarshaler), elem.Elem())
  42. return true
  43. default:
  44. switch keyType.Kind() {
  45. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  46. n, err := strconv.ParseInt(keyStr, 10, 64)
  47. if err != nil || reflect.Zero(keyType).OverflowInt(n) {
  48. iter.reportError("read map key as int64", "read int64 failed")
  49. return false
  50. }
  51. realVal.SetMapIndex(reflect.ValueOf(n).Convert(keyType), elem.Elem())
  52. return true
  53. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  54. n, err := strconv.ParseUint(keyStr, 10, 64)
  55. if err != nil || reflect.Zero(keyType).OverflowUint(n) {
  56. iter.reportError("read map key as uint64", "read uint64 failed")
  57. return false
  58. }
  59. realVal.SetMapIndex(reflect.ValueOf(n).Convert(keyType), elem.Elem())
  60. return true
  61. }
  62. }
  63. iter.reportError("read map key", "unexpected map key type "+keyType.String())
  64. return true
  65. })
  66. }
  67. type mapEncoder struct {
  68. mapType reflect.Type
  69. elemType reflect.Type
  70. elemEncoder Encoder
  71. mapInterface emptyInterface
  72. }
  73. func (encoder *mapEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
  74. mapInterface := encoder.mapInterface
  75. mapInterface.word = ptr
  76. realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
  77. realVal := reflect.ValueOf(*realInterface)
  78. stream.WriteObjectStart()
  79. for i, key := range realVal.MapKeys() {
  80. if i != 0 {
  81. stream.WriteMore()
  82. }
  83. encodeMapKey(key, stream)
  84. stream.writeByte(':')
  85. val := realVal.MapIndex(key).Interface()
  86. encoder.elemEncoder.encodeInterface(val, stream)
  87. }
  88. stream.WriteObjectEnd()
  89. }
  90. func encodeMapKey(key reflect.Value, stream *Stream) {
  91. if key.Kind() == reflect.String {
  92. stream.WriteString(key.String())
  93. return
  94. }
  95. if tm, ok := key.Interface().(encoding.TextMarshaler); ok {
  96. buf, err := tm.MarshalText()
  97. if err != nil {
  98. stream.Error = err
  99. return
  100. }
  101. stream.writeByte('"')
  102. stream.Write(buf)
  103. stream.writeByte('"')
  104. return
  105. }
  106. switch key.Kind() {
  107. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  108. stream.writeByte('"')
  109. stream.WriteInt64(key.Int())
  110. stream.writeByte('"')
  111. return
  112. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  113. stream.writeByte('"')
  114. stream.WriteUint64(key.Uint())
  115. stream.writeByte('"')
  116. return
  117. }
  118. stream.Error = &json.UnsupportedTypeError{key.Type()}
  119. }
  120. func (encoder *mapEncoder) encodeInterface(val interface{}, stream *Stream) {
  121. writeToStream(val, stream, encoder)
  122. }
  123. func (encoder *mapEncoder) isEmpty(ptr unsafe.Pointer) bool {
  124. mapInterface := encoder.mapInterface
  125. mapInterface.word = ptr
  126. realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
  127. realVal := reflect.ValueOf(*realInterface)
  128. return realVal.Len() == 0
  129. }