fuzzy_decoder.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. package extra
  2. import (
  3. "encoding/json"
  4. "github.com/json-iterator/go"
  5. "math"
  6. "reflect"
  7. "strings"
  8. "unsafe"
  9. )
  10. const maxUint = ^uint(0)
  11. const maxInt = int(maxUint >> 1)
  12. const minInt = -maxInt - 1
  13. // RegisterFuzzyDecoders decode input from PHP with tolerance.
  14. // It will handle string/number auto conversation, and treat empty [] as empty struct.
  15. func RegisterFuzzyDecoders() {
  16. jsoniter.RegisterExtension(&tolerateEmptyArrayExtension{})
  17. jsoniter.RegisterTypeDecoder("string", &fuzzyStringDecoder{})
  18. jsoniter.RegisterTypeDecoder("float32", &fuzzyFloat32Decoder{})
  19. jsoniter.RegisterTypeDecoder("float64", &fuzzyFloat64Decoder{})
  20. jsoniter.RegisterTypeDecoder("int", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  21. if isFloat {
  22. val := iter.ReadFloat64()
  23. if val > float64(maxInt) || val < float64(minInt) {
  24. iter.ReportError("fuzzy decode int", "exceed range")
  25. return
  26. }
  27. *((*int)(ptr)) = int(val)
  28. } else {
  29. *((*int)(ptr)) = iter.ReadInt()
  30. }
  31. }})
  32. jsoniter.RegisterTypeDecoder("uint", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  33. if isFloat {
  34. val := iter.ReadFloat64()
  35. if val > float64(maxUint) || val < 0 {
  36. iter.ReportError("fuzzy decode uint", "exceed range")
  37. return
  38. }
  39. *((*uint)(ptr)) = uint(val)
  40. } else {
  41. *((*uint)(ptr)) = iter.ReadUint()
  42. }
  43. }})
  44. jsoniter.RegisterTypeDecoder("int8", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  45. if isFloat {
  46. val := iter.ReadFloat64()
  47. if val > float64(math.MaxInt8) || val < float64(math.MinInt8) {
  48. iter.ReportError("fuzzy decode int8", "exceed range")
  49. return
  50. }
  51. *((*int8)(ptr)) = int8(val)
  52. } else {
  53. *((*int8)(ptr)) = iter.ReadInt8()
  54. }
  55. }})
  56. jsoniter.RegisterTypeDecoder("uint8", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  57. if isFloat {
  58. val := iter.ReadFloat64()
  59. if val > float64(math.MaxUint8) || val < 0 {
  60. iter.ReportError("fuzzy decode uint8", "exceed range")
  61. return
  62. }
  63. *((*uint8)(ptr)) = uint8(val)
  64. } else {
  65. *((*uint8)(ptr)) = iter.ReadUint8()
  66. }
  67. }})
  68. jsoniter.RegisterTypeDecoder("int16", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  69. if isFloat {
  70. val := iter.ReadFloat64()
  71. if val > float64(math.MaxInt16) || val < float64(math.MinInt16) {
  72. iter.ReportError("fuzzy decode int16", "exceed range")
  73. return
  74. }
  75. *((*int16)(ptr)) = int16(val)
  76. } else {
  77. *((*int16)(ptr)) = iter.ReadInt16()
  78. }
  79. }})
  80. jsoniter.RegisterTypeDecoder("uint16", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  81. if isFloat {
  82. val := iter.ReadFloat64()
  83. if val > float64(math.MaxUint16) || val < 0 {
  84. iter.ReportError("fuzzy decode uint16", "exceed range")
  85. return
  86. }
  87. *((*uint16)(ptr)) = uint16(val)
  88. } else {
  89. *((*uint16)(ptr)) = iter.ReadUint16()
  90. }
  91. }})
  92. jsoniter.RegisterTypeDecoder("int32", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  93. if isFloat {
  94. val := iter.ReadFloat64()
  95. if val > float64(math.MaxInt32) || val < float64(math.MinInt32) {
  96. iter.ReportError("fuzzy decode int32", "exceed range")
  97. return
  98. }
  99. *((*int32)(ptr)) = int32(val)
  100. } else {
  101. *((*int32)(ptr)) = iter.ReadInt32()
  102. }
  103. }})
  104. jsoniter.RegisterTypeDecoder("uint32", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  105. if isFloat {
  106. val := iter.ReadFloat64()
  107. if val > float64(math.MaxUint32) || val < 0 {
  108. iter.ReportError("fuzzy decode uint32", "exceed range")
  109. return
  110. }
  111. *((*uint32)(ptr)) = uint32(val)
  112. } else {
  113. *((*uint32)(ptr)) = iter.ReadUint32()
  114. }
  115. }})
  116. jsoniter.RegisterTypeDecoder("int64", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  117. if isFloat {
  118. val := iter.ReadFloat64()
  119. if val > float64(math.MaxInt64) || val < float64(math.MinInt64) {
  120. iter.ReportError("fuzzy decode int64", "exceed range")
  121. return
  122. }
  123. *((*int64)(ptr)) = int64(val)
  124. } else {
  125. *((*int64)(ptr)) = iter.ReadInt64()
  126. }
  127. }})
  128. jsoniter.RegisterTypeDecoder("uint64", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  129. if isFloat {
  130. val := iter.ReadFloat64()
  131. if val > float64(math.MaxUint64) || val < 0 {
  132. iter.ReportError("fuzzy decode uint64", "exceed range")
  133. return
  134. }
  135. *((*uint64)(ptr)) = uint64(val)
  136. } else {
  137. *((*uint64)(ptr)) = iter.ReadUint64()
  138. }
  139. }})
  140. }
  141. type tolerateEmptyArrayExtension struct {
  142. jsoniter.DummyExtension
  143. }
  144. func (extension *tolerateEmptyArrayExtension) DecorateDecoder(typ reflect.Type, decoder jsoniter.ValDecoder) jsoniter.ValDecoder {
  145. if typ.Kind() == reflect.Struct || typ.Kind() == reflect.Map {
  146. return &tolerateEmptyArrayDecoder{decoder}
  147. }
  148. return decoder
  149. }
  150. type tolerateEmptyArrayDecoder struct {
  151. valDecoder jsoniter.ValDecoder
  152. }
  153. func (decoder *tolerateEmptyArrayDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  154. if iter.WhatIsNext() == jsoniter.Array {
  155. iter.Skip()
  156. newIter := iter.Config().BorrowIterator([]byte("{}"))
  157. defer iter.Config().ReturnIterator(newIter)
  158. decoder.valDecoder.Decode(ptr, newIter)
  159. } else {
  160. decoder.valDecoder.Decode(ptr, iter)
  161. }
  162. }
  163. type fuzzyStringDecoder struct {
  164. }
  165. func (decoder *fuzzyStringDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  166. valueType := iter.WhatIsNext()
  167. switch valueType {
  168. case jsoniter.Number:
  169. var number json.Number
  170. iter.ReadVal(&number)
  171. *((*string)(ptr)) = string(number)
  172. case jsoniter.String:
  173. *((*string)(ptr)) = iter.ReadString()
  174. default:
  175. iter.ReportError("fuzzyStringDecoder", "not number or string")
  176. }
  177. }
  178. type fuzzyIntegerDecoder struct {
  179. fun func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator)
  180. }
  181. func (decoder *fuzzyIntegerDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  182. valueType := iter.WhatIsNext()
  183. var str string
  184. switch valueType {
  185. case jsoniter.Number:
  186. var number json.Number
  187. iter.ReadVal(&number)
  188. str = string(number)
  189. case jsoniter.String:
  190. str = iter.ReadString()
  191. default:
  192. iter.ReportError("fuzzyIntegerDecoder", "not number or string")
  193. }
  194. newIter := iter.Config().BorrowIterator([]byte(str))
  195. defer iter.Config().ReturnIterator(newIter)
  196. isFloat := strings.IndexByte(str, '.') != -1
  197. decoder.fun(isFloat, ptr, newIter)
  198. if newIter.Error != nil {
  199. iter.Error = newIter.Error
  200. }
  201. }
  202. type fuzzyFloat32Decoder struct {
  203. }
  204. func (decoder *fuzzyFloat32Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  205. valueType := iter.WhatIsNext()
  206. var str string
  207. switch valueType {
  208. case jsoniter.Number:
  209. *((*float32)(ptr)) = iter.ReadFloat32()
  210. case jsoniter.String:
  211. str = iter.ReadString()
  212. newIter := iter.Config().BorrowIterator([]byte(str))
  213. defer iter.Config().ReturnIterator(newIter)
  214. *((*float32)(ptr)) = newIter.ReadFloat32()
  215. if newIter.Error != nil {
  216. iter.Error = newIter.Error
  217. }
  218. default:
  219. iter.ReportError("fuzzyFloat32Decoder", "not number or string")
  220. }
  221. }
  222. type fuzzyFloat64Decoder struct {
  223. }
  224. func (decoder *fuzzyFloat64Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  225. valueType := iter.WhatIsNext()
  226. var str string
  227. switch valueType {
  228. case jsoniter.Number:
  229. *((*float64)(ptr)) = iter.ReadFloat64()
  230. case jsoniter.String:
  231. str = iter.ReadString()
  232. newIter := iter.Config().BorrowIterator([]byte(str))
  233. defer iter.Config().ReturnIterator(newIter)
  234. *((*float64)(ptr)) = newIter.ReadFloat64()
  235. if newIter.Error != nil {
  236. iter.Error = newIter.Error
  237. }
  238. default:
  239. iter.ReportError("fuzzyFloat32Decoder", "not number or string")
  240. }
  241. }