diff --git a/feature_any_float.go b/feature_any_float.go index 47350f8..dec4ff9 100644 --- a/feature_any_float.go +++ b/feature_any_float.go @@ -45,15 +45,21 @@ func (any *floatAny) ToUint() uint { if any.val > 0 { return uint(any.val) } - return uint(-any.val) + return 0 } func (any *floatAny) ToUint32() uint32 { - return uint32(any.val) + if any.val > 0 { + return uint32(any.val) + } + return 0 } func (any *floatAny) ToUint64() uint64 { - return uint64(any.val) + if any.val > 0 { + return uint64(any.val) + } + return 0 } func (any *floatAny) ToFloat32() float32 { diff --git a/feature_any_string.go b/feature_any_string.go index c58dda2..7b8c39a 100644 --- a/feature_any_string.go +++ b/feature_any_string.go @@ -119,12 +119,37 @@ func (any *stringAny) ToUint64() uint64 { } func (any *stringAny) ToFloat32() float32 { - parsed, _ := strconv.ParseFloat(any.val, 32) - return float32(parsed) + return float32(any.ToFloat64()) } func (any *stringAny) ToFloat64() float64 { - parsed, _ := strconv.ParseFloat(any.val, 64) + if len(any.val) == 0 { + return 0 + } + + // first char invalid + if any.val[0] != '+' && any.val[0] != '-' && (any.val[0] > '9' || any.val[0] < '0') { + return 0 + } + + // extract valid num expression from string + // eg 123true => 123, -12.12xxa => -12.12 + endPos := 1 + for i := 1; i < len(any.val); i++ { + if any.val[i] == '.' || any.val[i] == 'e' { + endPos = i + 1 + continue + } + + // end position is the first char which is not digit + if any.val[i] >= '0' && any.val[i] <= '9' { + endPos = i + 1 + } else { + endPos = i + break + } + } + parsed, _ := strconv.ParseFloat(any.val[:endPos], 64) return parsed } diff --git a/fuzzy_mode_convert_table.md b/fuzzy_mode_convert_table.md index 25c7196..7f73c34 100644 --- a/fuzzy_mode_convert_table.md +++ b/fuzzy_mode_convert_table.md @@ -1,7 +1,7 @@ -| json type \ dest type | bool | int | uint | string | -| --- | --- | --- | --- |--| -| number | positive => true
negative => true
zero => false| 23.2 => 23
-32.1 => -32| 12.1 => 12
-12.1 => 0|| -| string | empty string => false
string "0" => false
other strings => true | "123.32" => 123
"-123.4" => -123
"123.23xxxw" => 123
"abcde12" => 0
"-32.1" => -32| 13.2 => 13
-1.1 => 0 || -| bool | true => true
false => false| true => 1
false => 0 | true => 1
false => 0 || -| object | true | 0 | 0 || -| array | empty array => false
nonempty array => true| [] => 0
[1,2] => 1 | [] => 0
[1,2] => 1 || \ No newline at end of file +| json type \ dest type | bool | int | uint | float |string| +| --- | --- | --- | --- |--|--| +| number | positive => true
negative => true
zero => false| 23.2 => 23
-32.1 => -32| 12.1 => 12
-12.1 => 0|as normal|| +| string | empty string => false
string "0" => false
other strings => true | "123.32" => 123
"-123.4" => -123
"123.23xxxw" => 123
"abcde12" => 0
"-32.1" => -32| 13.2 => 13
-1.1 => 0 |12.1 => 12.1
-12.3 => -12.3
12.4xxa => 12.4
+1.1e2 =>110 || +| bool | true => true
false => false| true => 1
false => 0 | true => 1
false => 0 |true => 1
false => 0|| +| object | true | 0 | 0 |0|| +| array | empty array => false
nonempty array => true| [] => 0
[1,2] => 1 | [] => 0
[1,2] => 1 |[] => 0
[1,2] => 1|| \ No newline at end of file diff --git a/jsoniter_any_float_test.go b/jsoniter_any_float_test.go index d87c076..3845cd2 100644 --- a/jsoniter_any_float_test.go +++ b/jsoniter_any_float_test.go @@ -15,12 +15,15 @@ var floatConvertMap = map[string]float64{ `"false"`: 0, "123": 123, - `"123true"`: 0, + `"123true"`: 123, + `"+"`: 0, + `"-"`: 0, - `"-123true"`: 0, - "0": 0, - `"0"`: 0, - "-1": -1, + `"-123true"`: -123, + `"-99.9true"`: -99.9, + "0": 0, + `"0"`: 0, + "-1": -1, "1.1": 1.1, "0.0": 0, @@ -46,10 +49,25 @@ func Test_read_any_to_float(t *testing.T) { } } -func Test_read_float_as_any(t *testing.T) { +func Test_read_float_to_any(t *testing.T) { should := require.New(t) - any := Get([]byte("12.3")) + any := WrapFloat64(12.3) + anyFloat64 := float64(12.3) + //negaAnyFloat64 := float64(-1.1) + any2 := WrapFloat64(-1.1) should.Equal(float64(12.3), any.ToFloat64()) - should.Equal("12.3", any.ToString()) + //should.Equal("12.3", any.ToString()) should.True(any.ToBool()) + should.Equal(float32(anyFloat64), any.ToFloat32()) + should.Equal(int(anyFloat64), any.ToInt()) + should.Equal(int32(anyFloat64), any.ToInt32()) + should.Equal(int64(anyFloat64), any.ToInt64()) + should.Equal(uint(anyFloat64), any.ToUint()) + should.Equal(uint32(anyFloat64), any.ToUint32()) + should.Equal(uint64(anyFloat64), any.ToUint64()) + should.Equal(uint(0), any2.ToUint()) + should.Equal(uint32(0), any2.ToUint32()) + should.Equal(uint64(0), any2.ToUint64()) + should.Equal(any.ValueType(), Number) + } diff --git a/jsoniter_any_int_test.go b/jsoniter_any_int_test.go index 3a208c7..04c8722 100644 --- a/jsoniter_any_int_test.go +++ b/jsoniter_any_int_test.go @@ -2,7 +2,6 @@ package jsoniter import ( "fmt" - "io" "testing" "github.com/json-iterator/go/require" @@ -111,13 +110,65 @@ func Test_read_any_to_uint(t *testing.T) { } -func Test_read_int64_as_any(t *testing.T) { +func Test_read_int64_to_any(t *testing.T) { should := require.New(t) - any := Get([]byte("1234")) - should.Equal(1234, any.ToInt()) - should.Equal(io.EOF, any.LastError()) - should.Equal("1234", any.ToString()) - should.True(any.ToBool()) + any := WrapInt64(12345) + should.Equal(12345, any.ToInt()) + should.Equal(int32(12345), any.ToInt32()) + should.Equal(int64(12345), any.ToInt64()) + should.Equal(uint(12345), any.ToUint()) + should.Equal(uint32(12345), any.ToUint32()) + should.Equal(uint64(12345), any.ToUint64()) + should.Equal(float32(12345), any.ToFloat32()) + should.Equal(float64(12345), any.ToFloat64()) + should.Equal("12345", any.ToString()) + should.Equal(true, any.ToBool()) +} +func Test_read_int32_to_any(t *testing.T) { + should := require.New(t) + any := WrapInt32(12345) + should.Equal(12345, any.ToInt()) + should.Equal(int32(12345), any.ToInt32()) + should.Equal(int64(12345), any.ToInt64()) + should.Equal(uint(12345), any.ToUint()) + should.Equal(uint32(12345), any.ToUint32()) + should.Equal(uint64(12345), any.ToUint64()) + should.Equal(float32(12345), any.ToFloat32()) + should.Equal(float64(12345), any.ToFloat64()) + should.Equal("12345", any.ToString()) + should.Equal(true, any.ToBool()) +} + +func Test_read_uint32_to_any(t *testing.T) { + should := require.New(t) + any := WrapUint32(12345) + should.Equal(12345, any.ToInt()) + should.Equal(int32(12345), any.ToInt32()) + should.Equal(int64(12345), any.ToInt64()) + should.Equal(uint(12345), any.ToUint()) + should.Equal(uint32(12345), any.ToUint32()) + should.Equal(uint64(12345), any.ToUint64()) + should.Equal(float32(12345), any.ToFloat32()) + should.Equal(float64(12345), any.ToFloat64()) + should.Equal("12345", any.ToString()) + should.Equal(true, any.ToBool()) + should.Equal(any.ValueType(), Number) +} + +func Test_read_uint64_to_any(t *testing.T) { + should := require.New(t) + any := WrapUint64(12345) + should.Equal(12345, any.ToInt()) + should.Equal(int32(12345), any.ToInt32()) + should.Equal(int64(12345), any.ToInt64()) + should.Equal(uint(12345), any.ToUint()) + should.Equal(uint32(12345), any.ToUint32()) + should.Equal(uint64(12345), any.ToUint64()) + should.Equal(float32(12345), any.ToFloat32()) + should.Equal(float64(12345), any.ToFloat64()) + should.Equal("12345", any.ToString()) + should.Equal(true, any.ToBool()) + should.Equal(any.ValueType(), Number) } func Test_int_lazy_any_get(t *testing.T) { diff --git a/jsoniter_any_string_test.go b/jsoniter_any_string_test.go index 1567bdc..9512e05 100644 --- a/jsoniter_any_string_test.go +++ b/jsoniter_any_string_test.go @@ -6,6 +6,37 @@ import ( "github.com/json-iterator/go/require" ) +var stringConvertMap = map[string]string{ + "null": "", + "321.1": "321.1", + `"1.1"`: "1.1", + `"-123.1"`: "-123.1", + "0.0": "0.0", + "0": "0", + `"0"`: "0", + `"0.0"`: "0.0", + `"00.0"`: "00.0", + "true": "true", + "false": "false", + `"true"`: "true", + `"false"`: "false", + `"true123"`: "true123", + `"+1"`: "+1", + "[]": "[]", + "[1,2]": "[1,2]", + "{}": "{}", + "{1,2}": "{1,2}", + `{"a":1, "b":true}`: `{"a":1, "b":true}`, +} + +func Test_read_any_to_string(t *testing.T) { + should := require.New(t) + for k, v := range stringConvertMap { + any := Get([]byte(k)) + should.Equal(v, any.ToString(), "original val "+k) + } +} + func Test_read_string_as_any(t *testing.T) { should := require.New(t) any := Get([]byte(`"hello"`))