mirror of
https://github.com/json-iterator/go.git
synced 2025-04-17 11:26:35 +02:00
#68 handle float to int safely
This commit is contained in:
parent
a5ae3a2649
commit
8ef0c22f25
@ -4,11 +4,28 @@ import (
|
|||||||
"github.com/json-iterator/go"
|
"github.com/json-iterator/go"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const MaxUint = ^uint(0)
|
||||||
|
const MinUint = 0
|
||||||
|
const MaxInt = int(MaxUint >> 1)
|
||||||
|
const MinInt = -MaxInt - 1
|
||||||
|
|
||||||
func RegisterFuzzyDecoders() {
|
func RegisterFuzzyDecoders() {
|
||||||
jsoniter.RegisterTypeDecoder("string", &FuzzyStringDecoder{})
|
jsoniter.RegisterTypeDecoder("string", &FuzzyStringDecoder{})
|
||||||
jsoniter.RegisterTypeDecoder("int", &FuzzyIntDecoder{})
|
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 {
|
type FuzzyStringDecoder struct {
|
||||||
@ -28,20 +45,25 @@ func (decoder *FuzzyStringDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Ite
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type FuzzyIntDecoder struct {
|
type FuzzyNumberDecoder struct {
|
||||||
|
fun func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator, errorReporter *jsoniter.Iterator)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (decoder *FuzzyIntDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
func (decoder *FuzzyNumberDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||||
valueType := iter.WhatIsNext()
|
valueType := iter.WhatIsNext()
|
||||||
|
var str string
|
||||||
switch valueType {
|
switch valueType {
|
||||||
case jsoniter.Number:
|
case jsoniter.Number:
|
||||||
// use current iterator
|
var number json.Number
|
||||||
|
iter.ReadVal(&number)
|
||||||
|
str = string(number)
|
||||||
case jsoniter.String:
|
case jsoniter.String:
|
||||||
str := iter.ReadString()
|
str = iter.ReadString()
|
||||||
iter = iter.Config().BorrowIterator([]byte(str))
|
|
||||||
defer iter.Config().ReturnIterator(iter)
|
|
||||||
default:
|
default:
|
||||||
iter.ReportError("FuzzyIntDecoder", "not number or string")
|
iter.ReportError("FuzzyNumberDecoder", "not number or string")
|
||||||
}
|
}
|
||||||
*((*int)(ptr)) = int(iter.ReadFloat64())
|
newIter := iter.Config().BorrowIterator([]byte(str))
|
||||||
|
defer iter.Config().ReturnIterator(newIter)
|
||||||
|
isFloat := strings.IndexByte(str, '.') != -1
|
||||||
|
decoder.fun(isFloat, ptr, newIter, iter)
|
||||||
}
|
}
|
||||||
|
@ -51,3 +51,9 @@ func Test_float_to_int(t *testing.T) {
|
|||||||
should.Nil(jsoniter.UnmarshalFromString(`1.23`, &val))
|
should.Nil(jsoniter.UnmarshalFromString(`1.23`, &val))
|
||||||
should.Equal(1, val)
|
should.Equal(1, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_large_float_to_int(t *testing.T) {
|
||||||
|
should := require.New(t)
|
||||||
|
var val int
|
||||||
|
should.NotNil(jsoniter.UnmarshalFromString(`1234512345123451234512345.0`, &val))
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user