1
0
mirror of https://github.com/json-iterator/go.git synced 2024-11-24 08:22:14 +02:00
json-iterator/extra/fuzzy_decoder.go
2017-06-20 15:46:22 +08:00

70 lines
1.8 KiB
Go

package extra
import (
"github.com/json-iterator/go"
"unsafe"
"encoding/json"
"strings"
)
const MaxUint = ^uint(0)
const MinUint = 0
const MaxInt = int(MaxUint >> 1)
const MinInt = -MaxInt - 1
func RegisterFuzzyDecoders() {
jsoniter.RegisterTypeDecoder("string", &FuzzyStringDecoder{})
jsoniter.RegisterTypeDecoder("int", &FuzzyNumberDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator, errorReporter *jsoniter.Iterator) {
if isFloat {
val := iter.ReadFloat64()
if val > float64(MaxInt) || val < float64(MinInt) {
errorReporter.ReportError("fuzzy decode int", "exceed range")
return
}
*((*int)(ptr)) = int(val)
} else {
*((*int)(ptr)) = iter.ReadInt()
}
}})
}
type FuzzyStringDecoder struct {
}
func (decoder *FuzzyStringDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
valueType := iter.WhatIsNext()
switch valueType {
case jsoniter.Number:
var number json.Number
iter.ReadVal(&number)
*((*string)(ptr)) = string(number)
case jsoniter.String:
*((*string)(ptr)) = iter.ReadString()
default:
iter.ReportError("FuzzyStringDecoder", "not number or string")
}
}
type FuzzyNumberDecoder struct {
fun func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator, errorReporter *jsoniter.Iterator)
}
func (decoder *FuzzyNumberDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
valueType := iter.WhatIsNext()
var str string
switch valueType {
case jsoniter.Number:
var number json.Number
iter.ReadVal(&number)
str = string(number)
case jsoniter.String:
str = iter.ReadString()
default:
iter.ReportError("FuzzyNumberDecoder", "not number or string")
}
newIter := iter.Config().BorrowIterator([]byte(str))
defer iter.Config().ReturnIterator(newIter)
isFloat := strings.IndexByte(str, '.') != -1
decoder.fun(isFloat, ptr, newIter, iter)
}