fuzzy_decoder.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package extra
  2. import (
  3. "github.com/json-iterator/go"
  4. "unsafe"
  5. "encoding/json"
  6. "strings"
  7. )
  8. const MaxUint = ^uint(0)
  9. const MinUint = 0
  10. const MaxInt = int(MaxUint >> 1)
  11. const MinInt = -MaxInt - 1
  12. func RegisterFuzzyDecoders() {
  13. jsoniter.RegisterTypeDecoder("string", &FuzzyStringDecoder{})
  14. jsoniter.RegisterTypeDecoder("int", &FuzzyNumberDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator, errorReporter *jsoniter.Iterator) {
  15. if isFloat {
  16. val := iter.ReadFloat64()
  17. if val > float64(MaxInt) || val < float64(MinInt) {
  18. errorReporter.ReportError("fuzzy decode int", "exceed range")
  19. return
  20. }
  21. *((*int)(ptr)) = int(val)
  22. } else {
  23. *((*int)(ptr)) = iter.ReadInt()
  24. }
  25. }})
  26. }
  27. type FuzzyStringDecoder struct {
  28. }
  29. func (decoder *FuzzyStringDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  30. valueType := iter.WhatIsNext()
  31. switch valueType {
  32. case jsoniter.Number:
  33. var number json.Number
  34. iter.ReadVal(&number)
  35. *((*string)(ptr)) = string(number)
  36. case jsoniter.String:
  37. *((*string)(ptr)) = iter.ReadString()
  38. default:
  39. iter.ReportError("FuzzyStringDecoder", "not number or string")
  40. }
  41. }
  42. type FuzzyNumberDecoder struct {
  43. fun func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator, errorReporter *jsoniter.Iterator)
  44. }
  45. func (decoder *FuzzyNumberDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
  46. valueType := iter.WhatIsNext()
  47. var str string
  48. switch valueType {
  49. case jsoniter.Number:
  50. var number json.Number
  51. iter.ReadVal(&number)
  52. str = string(number)
  53. case jsoniter.String:
  54. str = iter.ReadString()
  55. default:
  56. iter.ReportError("FuzzyNumberDecoder", "not number or string")
  57. }
  58. newIter := iter.Config().BorrowIterator([]byte(str))
  59. defer iter.Config().ReturnIterator(newIter)
  60. isFloat := strings.IndexByte(str, '.') != -1
  61. decoder.fun(isFloat, ptr, newIter, iter)
  62. }