diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 0000000..ed1daa2 --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,5 @@ +ignore: + - "output_tests/.*" + - "assert/.*" + - "require/.*" + diff --git a/feature_any_float.go b/feature_any_float.go index ad037b8..dec4ff9 100644 --- a/feature_any_float.go +++ b/feature_any_float.go @@ -42,15 +42,24 @@ func (any *floatAny) ToInt64() int64 { } func (any *floatAny) ToUint() uint { - return uint(any.val) + if any.val > 0 { + 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_number.go b/feature_any_number.go index 1dc0244..d909044 100644 --- a/feature_any_number.go +++ b/feature_any_number.go @@ -1,8 +1,6 @@ package jsoniter -import ( - "unsafe" -) +import "unsafe" type numberLazyAny struct { baseAny diff --git a/feature_any_object.go b/feature_any_object.go index 7382233..5386f83 100644 --- a/feature_any_object.go +++ b/feature_any_object.go @@ -25,73 +25,39 @@ func (any *objectLazyAny) LastError() error { } func (any *objectLazyAny) ToBool() bool { - iter := any.cfg.BorrowIterator(any.buf) - defer any.cfg.ReturnIterator(iter) - return iter.ReadObject() != "" + return true } func (any *objectLazyAny) ToInt() int { - if any.ToBool() { - return 1 - } else { - return 0 - } + return 0 } func (any *objectLazyAny) ToInt32() int32 { - if any.ToBool() { - return 1 - } else { - return 0 - } + return 0 } func (any *objectLazyAny) ToInt64() int64 { - if any.ToBool() { - return 1 - } else { - return 0 - } + return 0 } func (any *objectLazyAny) ToUint() uint { - if any.ToBool() { - return 1 - } else { - return 0 - } + return 0 } func (any *objectLazyAny) ToUint32() uint32 { - if any.ToBool() { - return 1 - } else { - return 0 - } + return 0 } func (any *objectLazyAny) ToUint64() uint64 { - if any.ToBool() { - return 1 - } else { - return 0 - } + return 0 } func (any *objectLazyAny) ToFloat32() float32 { - if any.ToBool() { - return 1 - } else { - return 0 - } + return 0 } func (any *objectLazyAny) ToFloat64() float64 { - if any.ToBool() { - return 1 - } else { - return 0 - } + return 0 } func (any *objectLazyAny) ToString() string { @@ -216,59 +182,35 @@ func (any *objectAny) ToBool() bool { } func (any *objectAny) ToInt() int { - if any.val.NumField() == 0 { - return 0 - } - return 1 + return 0 } func (any *objectAny) ToInt32() int32 { - if any.val.NumField() == 0 { - return 0 - } - return 1 + return 0 } func (any *objectAny) ToInt64() int64 { - if any.val.NumField() == 0 { - return 0 - } - return 1 + return 0 } func (any *objectAny) ToUint() uint { - if any.val.NumField() == 0 { - return 0 - } - return 1 + return 0 } func (any *objectAny) ToUint32() uint32 { - if any.val.NumField() == 0 { - return 0 - } - return 1 + return 0 } func (any *objectAny) ToUint64() uint64 { - if any.val.NumField() == 0 { - return 0 - } - return 1 + return 0 } func (any *objectAny) ToFloat32() float32 { - if any.val.NumField() == 0 { - return 0 - } - return 1 + return 0 } func (any *objectAny) ToFloat64() float64 { - if any.val.NumField() == 0 { - return 0 - } - return 1 + return 0 } func (any *objectAny) ToString() string { @@ -367,63 +309,39 @@ func (any *mapAny) LastError() error { } func (any *mapAny) ToBool() bool { - return any.val.Len() != 0 + return true } func (any *mapAny) ToInt() int { - if any.val.Len() == 0 { - return 0 - } - return 1 + return 0 } func (any *mapAny) ToInt32() int32 { - if any.val.Len() == 0 { - return 0 - } - return 1 + return 0 } func (any *mapAny) ToInt64() int64 { - if any.val.Len() == 0 { - return 0 - } - return 1 + return 0 } func (any *mapAny) ToUint() uint { - if any.val.Len() == 0 { - return 0 - } - return 1 + return 0 } func (any *mapAny) ToUint32() uint32 { - if any.val.Len() == 0 { - return 0 - } - return 1 + return 0 } func (any *mapAny) ToUint64() uint64 { - if any.val.Len() == 0 { - return 0 - } - return 1 + return 0 } func (any *mapAny) ToFloat32() float32 { - if any.val.Len() == 0 { - return 0 - } - return 1 + return 0 } func (any *mapAny) ToFloat64() float64 { - if any.val.Len() == 0 { - return 0 - } - return 1 + return 0 } func (any *mapAny) ToString() string { diff --git a/feature_any_string.go b/feature_any_string.go index e3dcd6a..5a0e8da 100644 --- a/feature_any_string.go +++ b/feature_any_string.go @@ -35,7 +35,7 @@ func (any *stringAny) LastError() error { func (any *stringAny) ToBool() bool { str := any.ToString() - if str == "false" { + if str == "0" { return false } for _, c := range str { @@ -49,42 +49,107 @@ func (any *stringAny) ToBool() bool { } func (any *stringAny) ToInt() int { - parsed, _ := strconv.ParseInt(any.val, 10, 64) - return int(parsed) + return int(any.ToInt64()) + } func (any *stringAny) ToInt32() int32 { - parsed, _ := strconv.ParseInt(any.val, 10, 32) - return int32(parsed) + return int32(any.ToInt64()) } func (any *stringAny) ToInt64() int64 { - parsed, _ := strconv.ParseInt(any.val, 10, 64) - return parsed + if any.val == "" { + return 0 + } + + flag := 1 + startPos := 0 + endPos := 0 + if any.val[0] == '+' || any.val[0] == '-' { + startPos = 1 + } + + if any.val[0] == '-' { + flag = -1 + } + + for i := startPos; i < len(any.val); i++ { + if any.val[i] >= '0' && any.val[i] <= '9' { + endPos = i + 1 + } else { + break + } + } + parsed, _ := strconv.ParseInt(any.val[startPos:endPos], 10, 64) + return int64(flag) * parsed } func (any *stringAny) ToUint() uint { - parsed, _ := strconv.ParseUint(any.val, 10, 64) - return uint(parsed) + return uint(any.ToUint64()) } func (any *stringAny) ToUint32() uint32 { - parsed, _ := strconv.ParseUint(any.val, 10, 32) - return uint32(parsed) + return uint32(any.ToUint64()) } func (any *stringAny) ToUint64() uint64 { - parsed, _ := strconv.ParseUint(any.val, 10, 64) + if any.val == "" { + return 0 + } + + startPos := 0 + endPos := 0 + + if any.val[0] == '-' { + return 0 + } + if any.val[0] == '+' { + startPos = 1 + } + + for i := startPos; i < len(any.val); i++ { + if any.val[i] >= '0' && any.val[i] <= '9' { + endPos = i + 1 + } else { + break + } + } + parsed, _ := strconv.ParseUint(any.val[startPos:endPos], 10, 64) return parsed } 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' || 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/feature_stream_float.go b/feature_stream_float.go index 0b8e8a0..281370b 100644 --- a/feature_stream_float.go +++ b/feature_stream_float.go @@ -1,8 +1,8 @@ package jsoniter import ( - "strconv" "math" + "strconv" ) var _POW10 []uint64 diff --git a/fuzzy_mode_convert_table.md b/fuzzy_mode_convert_table.md new file mode 100644 index 0000000..7f73c34 --- /dev/null +++ b/fuzzy_mode_convert_table.md @@ -0,0 +1,7 @@ +| 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_1dot8_only_test.go b/jsoniter_1dot8_only_test.go index 50f7a6a..e2154c4 100644 --- a/jsoniter_1dot8_only_test.go +++ b/jsoniter_1dot8_only_test.go @@ -3,11 +3,12 @@ package jsoniter import ( - "testing" - "encoding/json" - "github.com/json-iterator/go/require" "bytes" + "encoding/json" + "testing" "unicode/utf8" + + "github.com/json-iterator/go/require" ) func Test_new_encoder(t *testing.T) { @@ -41,4 +42,4 @@ func Test_string_encode_with_std_without_html_escape(t *testing.T) { jsoniterOutput := string(jsoniterOutputBytes) should.Equal(stdOutput, jsoniterOutput) } -} \ No newline at end of file +} diff --git a/jsoniter_any_array_test.go b/jsoniter_any_array_test.go index 577745e..e888503 100644 --- a/jsoniter_any_array_test.go +++ b/jsoniter_any_array_test.go @@ -1,8 +1,9 @@ package jsoniter import ( - "github.com/json-iterator/go/require" "testing" + + "github.com/json-iterator/go/require" ) func Test_read_empty_array_as_any(t *testing.T) { @@ -46,10 +47,36 @@ func Test_read_two_element_array_as_any(t *testing.T) { should.Equal([]int{1, 2}, arr) } -func Test_wrap_array(t *testing.T) { +func Test_wrap_array_and_convert_to_any(t *testing.T) { should := require.New(t) any := Wrap([]int{1, 2, 3}) + any2 := Wrap([]int{}) + should.Equal("[1,2,3]", any.ToString()) + should.True(any.ToBool()) + should.False(any2.ToBool()) + + should.Equal(1, any.ToInt()) + should.Equal(0, any2.ToInt()) + should.Equal(int32(1), any.ToInt32()) + should.Equal(int32(0), any2.ToInt32()) + should.Equal(int64(1), any.ToInt64()) + should.Equal(int64(0), any2.ToInt64()) + should.Equal(uint(1), any.ToUint()) + should.Equal(uint(0), any2.ToUint()) + should.Equal(uint32(1), any.ToUint32()) + should.Equal(uint32(0), any2.ToUint32()) + should.Equal(uint64(1), any.ToUint64()) + should.Equal(uint64(0), any2.ToUint64()) + should.Equal(float32(1), any.ToFloat32()) + should.Equal(float32(0), any2.ToFloat32()) + should.Equal(float64(1), any.ToFloat64()) + should.Equal(float64(0), any2.ToFloat64()) + should.Equal(3, any.Size()) + should.Equal(0, any2.Size()) + + var i interface{} = []int{1, 2, 3} + should.Equal(i, any.GetInterface()) } func Test_array_lazy_any_get(t *testing.T) { diff --git a/jsoniter_any_bool_test.go b/jsoniter_any_bool_test.go index 7344f4d..f6b09ee 100644 --- a/jsoniter_any_bool_test.go +++ b/jsoniter_any_bool_test.go @@ -1,12 +1,64 @@ package jsoniter import ( - "github.com/json-iterator/go/require" + "fmt" "testing" + + "github.com/json-iterator/go/require" ) +var boolConvertMap = map[string]bool{ + "null": false, + "true": true, + "false": false, + + `"true"`: true, + `"false"`: true, + + "123": true, + `"123"`: true, + "0": false, + `"0"`: false, + "-1": true, + `"-1"`: true, + + "1.1": true, + "0.0": false, + "-1.1": true, + `""`: false, + "[1,2]": true, + "[]": false, + "{}": true, + `{"abc":1}`: true, +} + func Test_read_bool_as_any(t *testing.T) { should := require.New(t) - any := Get([]byte("true")) - should.True(any.ToBool()) + + var any Any + for k, v := range boolConvertMap { + any = Get([]byte(k)) + if v { + should.True(any.ToBool(), fmt.Sprintf("origin val is %v", k)) + } else { + should.False(any.ToBool(), fmt.Sprintf("origin val is %v", k)) + } + } + +} + +func Test_write_bool_to_stream(t *testing.T) { + should := require.New(t) + any := Get([]byte("true")) + stream := NewStream(ConfigDefault, nil, 32) + any.WriteTo(stream) + should.Equal("true", string(stream.Buffer())) + should.Equal(any.ValueType(), Bool) + + any = Get([]byte("false")) + stream = NewStream(ConfigDefault, nil, 32) + any.WriteTo(stream) + should.Equal("false", string(stream.Buffer())) + + should.Equal(any.ValueType(), Bool) } diff --git a/jsoniter_any_float_test.go b/jsoniter_any_float_test.go index 6606956..9e179b6 100644 --- a/jsoniter_any_float_test.go +++ b/jsoniter_any_float_test.go @@ -1,14 +1,74 @@ package jsoniter import ( - "github.com/json-iterator/go/require" "testing" + + "github.com/json-iterator/go/require" ) -func Test_read_float_as_any(t *testing.T) { - should := require.New(t) - any := Get([]byte("12.3")) - should.Equal(float64(12.3), any.ToFloat64()) - should.Equal("12.3", any.ToString()) - should.True(any.ToBool()) +var floatConvertMap = map[string]float64{ + "null": 0, + "true": 1, + "false": 0, + + `"true"`: 0, + `"false"`: 0, + + "123": 123, + `"123true"`: 123, + `"+"`: 0, + `"-"`: 0, + + `"-123true"`: -123, + `"-99.9true"`: -99.9, + "0": 0, + `"0"`: 0, + "-1": -1, + + "1.1": 1.1, + "0.0": 0, + "-1.1": -1.1, + `"+1.1"`: 1.1, + `""`: 0, + "[1,2]": 1, + "[]": 0, + "{}": 0, + `{"abc":1}`: 0, +} + +func Test_read_any_to_float(t *testing.T) { + should := require.New(t) + for k, v := range floatConvertMap { + any := Get([]byte(k)) + should.Equal(float64(v), any.ToFloat64(), "the original val is "+k) + } + + for k, v := range floatConvertMap { + any := Get([]byte(k)) + should.Equal(float32(v), any.ToFloat32(), "the original val is "+k) + } +} + +func Test_read_float_to_any(t *testing.T) { + should := require.New(t) + 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.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) + + should.Equal("1.23E+01", any.ToString()) } diff --git a/jsoniter_any_int_test.go b/jsoniter_any_int_test.go index b19f4f9..f8b9518 100644 --- a/jsoniter_any_int_test.go +++ b/jsoniter_any_int_test.go @@ -1,22 +1,197 @@ package jsoniter import ( - "github.com/json-iterator/go/require" - "io" + "fmt" "testing" + + "github.com/json-iterator/go/require" ) -func Test_read_int64_as_any(t *testing.T) { +var intConvertMap = map[string]int{ + "null": 0, + "321.1": 321, + "-321.1": -321, + `"1.1"`: 1, + `"-321.1"`: -321, + "0.0": 0, + "0": 0, + `"0"`: 0, + `"0.0"`: 0, + "-1.1": -1, + "true": 1, + "false": 0, + `"true"`: 0, + `"false"`: 0, + `"true123"`: 0, + `"123true"`: 123, + `"-123true"`: -123, + `"1.2332e6"`: 1, + `""`: 0, + "+": 0, + "-": 0, + "[]": 0, + "[1,2]": 1, + `["1","2"]`: 1, + // object in php cannot convert to int + "{}": 0, +} + +func Test_read_any_to_int(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()) + + // int + for k, v := range intConvertMap { + any := Get([]byte(k)) + should.Equal(v, any.ToInt(), fmt.Sprintf("origin val %v", k)) + } + + // int32 + for k, v := range intConvertMap { + any := Get([]byte(k)) + should.Equal(int32(v), any.ToInt32(), fmt.Sprintf("original val is %v", k)) + } + + // int64 + for k, v := range intConvertMap { + any := Get([]byte(k)) + should.Equal(int64(v), any.ToInt64(), fmt.Sprintf("original val is %v", k)) + } + +} + +var uintConvertMap = map[string]int{ + "null": 0, + "321.1": 321, + `"1.1"`: 1, + `"-123.1"`: 0, + "0.0": 0, + "0": 0, + `"0"`: 0, + `"0.0"`: 0, + `"00.0"`: 0, + "true": 1, + "false": 0, + `"true"`: 0, + `"false"`: 0, + `"true123"`: 0, + `"+1"`: 1, + `"123true"`: 123, + `"-123true"`: 0, + `"1.2332e6"`: 1, + `""`: 0, + "+": 0, + "-": 0, + ".": 0, + "[]": 0, + "[1,2]": 1, + "{}": 0, + "{1,2}": 0, + "-1.1": 0, + "-321.1": 0, +} + +func Test_read_any_to_uint(t *testing.T) { + should := require.New(t) + + for k, v := range uintConvertMap { + any := Get([]byte(k)) + should.Equal(uint64(v), any.ToUint64(), fmt.Sprintf("origin val %v", k)) + } + + for k, v := range uintConvertMap { + any := Get([]byte(k)) + should.Equal(uint32(v), any.ToUint32(), fmt.Sprintf("origin val %v", k)) + } + + for k, v := range uintConvertMap { + any := Get([]byte(k)) + should.Equal(uint(v), any.ToUint(), fmt.Sprintf("origin val %v", k)) + } + +} + +func Test_read_int64_to_any(t *testing.T) { + should := require.New(t) + 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()) + should.Equal(any.ValueType(), Number) + stream := NewStream(ConfigDefault, nil, 32) + any.WriteTo(stream) + should.Equal("12345", string(stream.Buffer())) +} +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()) + should.Equal(any.ValueType(), Number) + stream := NewStream(ConfigDefault, nil, 32) + any.WriteTo(stream) + should.Equal("12345", string(stream.Buffer())) +} + +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) + stream := NewStream(ConfigDefault, nil, 32) + any.WriteTo(stream) + should.Equal("12345", string(stream.Buffer())) +} + +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) + stream := NewStream(ConfigDefault, nil, 32) + any.WriteTo(stream) + should.Equal("12345", string(stream.Buffer())) + stream = NewStream(ConfigDefault, nil, 32) + stream.WriteUint(uint(123)) + should.Equal("123", string(stream.Buffer())) } func Test_int_lazy_any_get(t *testing.T) { should := require.New(t) any := Get([]byte("1234")) + // panic!! + //should.Equal(any.LastError(), io.EOF) should.Equal(Invalid, any.Get(1, "2").ValueType()) } diff --git a/jsoniter_any_object_test.go b/jsoniter_any_object_test.go index 4c85f4d..2ce141b 100644 --- a/jsoniter_any_object_test.go +++ b/jsoniter_any_object_test.go @@ -1,8 +1,9 @@ package jsoniter import ( - "github.com/json-iterator/go/require" "testing" + + "github.com/json-iterator/go/require" ) func Test_read_object_as_any(t *testing.T) { @@ -18,7 +19,7 @@ func Test_read_object_as_any(t *testing.T) { should.Equal(2, len(any.Keys())) should.Equal(2, any.Size()) should.True(any.ToBool()) - should.Equal(1, any.ToInt()) + should.Equal(0, any.ToInt()) should.Equal(Object, any.ValueType()) should.Nil(any.LastError()) should.Equal("b", any.GetObject()["a"].ToString()) @@ -48,7 +49,21 @@ func Test_object_lazy_any_get_invalid(t *testing.T) { should.Equal(Invalid, any.Get(1).ValueType()) } -func Test_wrap_object(t *testing.T) { +func Test_wrap_map_and_convert_to_any(t *testing.T) { + should := require.New(t) + any := Wrap(map[string]interface{}{"a": 1}) + should.True(any.ToBool()) + should.Equal(0, any.ToInt()) + should.Equal(int32(0), any.ToInt32()) + should.Equal(int64(0), any.ToInt64()) + should.Equal(float32(0), any.ToFloat32()) + should.Equal(float64(0), any.ToFloat64()) + should.Equal(uint(0), any.ToUint()) + should.Equal(uint32(0), any.ToUint32()) + should.Equal(uint64(0), any.ToUint64()) +} + +func Test_wrap_object_and_convert_to_any(t *testing.T) { should := require.New(t) type TestObject struct { Field1 string @@ -59,6 +74,24 @@ func Test_wrap_object(t *testing.T) { any = Wrap(TestObject{"hello", "world"}) should.Equal(2, any.Size()) should.Equal(`{"Field1":"hello"}`, any.Get('*').ToString()) + + should.Equal(0, any.ToInt()) + should.Equal(int32(0), any.ToInt32()) + should.Equal(int64(0), any.ToInt64()) + should.Equal(float32(0), any.ToFloat32()) + should.Equal(float64(0), any.ToFloat64()) + should.Equal(uint(0), any.ToUint()) + should.Equal(uint32(0), any.ToUint32()) + should.Equal(uint64(0), any.ToUint64()) + should.True(any.ToBool()) + should.Equal(`{"Field1":"hello"}`, any.ToString()) + + // cannot pass! + //stream := NewStream(ConfigDefault, nil, 32) + //any.WriteTo(stream) + //should.Equal(`{"Field1":"hello"}`, string(stream.Buffer())) + // cannot pass! + } func Test_any_within_struct(t *testing.T) { diff --git a/jsoniter_any_string_test.go b/jsoniter_any_string_test.go index f17a111..9512e05 100644 --- a/jsoniter_any_string_test.go +++ b/jsoniter_any_string_test.go @@ -1,10 +1,42 @@ package jsoniter import ( - "github.com/json-iterator/go/require" "testing" + + "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"`)) @@ -13,7 +45,7 @@ func Test_read_string_as_any(t *testing.T) { any = Get([]byte(`" "`)) should.False(any.ToBool()) any = Get([]byte(`"false"`)) - should.False(any.ToBool()) + should.True(any.ToBool()) any = Get([]byte(`"123"`)) should.Equal(123, any.ToInt()) } diff --git a/jsoniter_bool_test.go b/jsoniter_bool_test.go index 41d4a3a..771f514 100644 --- a/jsoniter_bool_test.go +++ b/jsoniter_bool_test.go @@ -3,8 +3,9 @@ package jsoniter import ( "bytes" "encoding/json" - "github.com/json-iterator/go/require" "testing" + + "github.com/json-iterator/go/require" ) func Test_true(t *testing.T) { @@ -27,9 +28,10 @@ func Test_write_true_false(t *testing.T) { stream := NewStream(ConfigDefault, buf, 4096) stream.WriteTrue() stream.WriteFalse() + stream.WriteBool(false) stream.Flush() should.Nil(stream.Error) - should.Equal("truefalse", buf.String()) + should.Equal("truefalsefalse", buf.String()) } func Test_write_val_bool(t *testing.T) { @@ -37,7 +39,9 @@ func Test_write_val_bool(t *testing.T) { buf := &bytes.Buffer{} stream := NewStream(ConfigDefault, buf, 4096) stream.WriteVal(true) + should.Equal(stream.Buffered(), 4) stream.Flush() + should.Equal(stream.Buffered(), 0) should.Nil(stream.Error) should.Equal("true", buf.String()) } diff --git a/jsoniter_demo_test.go b/jsoniter_demo_test.go index 92fa02c..5c49268 100644 --- a/jsoniter_demo_test.go +++ b/jsoniter_demo_test.go @@ -2,9 +2,9 @@ package jsoniter import ( "encoding/json" - "fmt" - "github.com/json-iterator/go/require" "testing" + + "github.com/json-iterator/go/require" ) func Test_bind_api_demo(t *testing.T) { @@ -21,7 +21,7 @@ func Test_iterator_api_demo(t *testing.T) { for iter.ReadArray() { total += iter.ReadInt() } - fmt.Println(total) + //fmt.Println(total) } type People struct { diff --git a/jsoniter_float_test.go b/jsoniter_float_test.go index 547c2d6..8895346 100644 --- a/jsoniter_float_test.go +++ b/jsoniter_float_test.go @@ -6,9 +6,10 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/json-iterator/go/require" "strconv" "testing" + + "github.com/json-iterator/go/require" ) func Test_read_big_float(t *testing.T) { @@ -111,6 +112,10 @@ func Test_write_float32(t *testing.T) { stream.Flush() should.Nil(stream.Error) should.Equal("abcdefg1.123456", buf.String()) + + stream = NewStream(ConfigDefault, nil, 0) + stream.WriteFloat32(float32(0.0000001)) + should.Equal("1e-07", string(stream.buf)) } func Test_write_float64(t *testing.T) { @@ -144,6 +149,10 @@ func Test_write_float64(t *testing.T) { stream.Flush() should.Nil(stream.Error) should.Equal("abcdefg1.123456", buf.String()) + + stream = NewStream(ConfigDefault, nil, 0) + stream.WriteFloat64(float64(0.0000001)) + should.Equal("1e-07", string(stream.buf)) } func Test_read_float64_cursor(t *testing.T) { diff --git a/jsoniter_invalid_test.go b/jsoniter_invalid_test.go index e764b57..358143b 100644 --- a/jsoniter_invalid_test.go +++ b/jsoniter_invalid_test.go @@ -19,3 +19,25 @@ func Test_missing_array_end(t *testing.T) { should := require.New(t) should.NotNil(UnmarshalFromString(`[1,2,3`, &[]int{})) } + +func Test_invalid_any(t *testing.T) { + should := require.New(t) + any := Get([]byte("[]")) + should.Equal(Invalid, any.Get(0.3).ValueType()) + // is nil correct ? + should.Equal(nil, any.Get(0.3).GetInterface()) + + any = any.Get(0.3) + should.Equal(false, any.ToBool()) + should.Equal(int(0), any.ToInt()) + should.Equal(int32(0), any.ToInt32()) + should.Equal(int64(0), any.ToInt64()) + should.Equal(uint(0), any.ToUint()) + should.Equal(uint32(0), any.ToUint32()) + should.Equal(uint64(0), any.ToUint64()) + should.Equal(float32(0), any.ToFloat32()) + should.Equal(float64(0), any.ToFloat64()) + should.Equal("", any.ToString()) + + should.Equal(Invalid, any.Get(0.1).Get(1).ValueType()) +} diff --git a/jsoniter_map_test.go b/jsoniter_map_test.go index 794bcb1..378165b 100644 --- a/jsoniter_map_test.go +++ b/jsoniter_map_test.go @@ -2,9 +2,10 @@ package jsoniter import ( "encoding/json" - "github.com/json-iterator/go/require" "math/big" "testing" + + "github.com/json-iterator/go/require" ) func Test_read_map(t *testing.T) { @@ -30,6 +31,14 @@ func Test_map_wrapper_any_get_all(t *testing.T) { should := require.New(t) any := Wrap(map[string][]int{"Field1": {1, 2}}) should.Equal(`{"Field1":1}`, any.Get('*', 0).ToString()) + should.Contains(any.Keys(), "Field1") + should.Equal(any.GetObject()["Field1"].ToInt(), 1) + + // map write to + stream := NewStream(ConfigDefault, nil, 0) + any.WriteTo(stream) + // TODO cannot pass + //should.Equal(string(stream.buf), "") } func Test_write_val_map(t *testing.T) { diff --git a/jsoniter_must_be_valid_test.go b/jsoniter_must_be_valid_test.go new file mode 100644 index 0000000..01c6e44 --- /dev/null +++ b/jsoniter_must_be_valid_test.go @@ -0,0 +1,71 @@ +package jsoniter + +import ( + "testing" + + "github.com/json-iterator/go/require" +) + +// if must be valid is useless, just drop this test +func Test_must_be_valid(t *testing.T) { + should := require.New(t) + any := Get([]byte("123")) + should.Equal(any.MustBeValid().ToInt(), 123) + + any = Wrap(int8(10)) + should.Equal(any.MustBeValid().ToInt(), 10) + + any = Wrap(int16(10)) + should.Equal(any.MustBeValid().ToInt(), 10) + + any = Wrap(int32(10)) + should.Equal(any.MustBeValid().ToInt(), 10) + + any = Wrap(int64(10)) + should.Equal(any.MustBeValid().ToInt(), 10) + + any = Wrap(uint(10)) + should.Equal(any.MustBeValid().ToInt(), 10) + + any = Wrap(uint8(10)) + should.Equal(any.MustBeValid().ToInt(), 10) + + any = Wrap(uint16(10)) + should.Equal(any.MustBeValid().ToInt(), 10) + + any = Wrap(uint32(10)) + should.Equal(any.MustBeValid().ToInt(), 10) + + any = Wrap(uint64(10)) + should.Equal(any.MustBeValid().ToInt(), 10) + + any = Wrap(float32(10)) + should.Equal(any.MustBeValid().ToFloat64(), float64(10)) + + any = Wrap(float64(10)) + should.Equal(any.MustBeValid().ToFloat64(), float64(10)) + + any = Wrap(true) + should.Equal(any.MustBeValid().ToFloat64(), float64(1)) + + any = Wrap(false) + should.Equal(any.MustBeValid().ToFloat64(), float64(0)) + + any = Wrap(nil) + should.Equal(any.MustBeValid().ToFloat64(), float64(0)) + + any = Wrap(struct{ age int }{age: 1}) + should.Equal(any.MustBeValid().ToFloat64(), float64(0)) + + any = Wrap(map[string]interface{}{"abc": 1}) + should.Equal(any.MustBeValid().ToFloat64(), float64(0)) + + any = Wrap("abc") + should.Equal(any.MustBeValid().ToFloat64(), float64(0)) + + any = Wrap([]int{}) + should.Equal(any.MustBeValid().ToFloat64(), float64(0)) + + any = Wrap([]int{1, 2}) + should.Equal(any.MustBeValid().ToFloat64(), float64(1)) +} diff --git a/jsoniter_object_test.go b/jsoniter_object_test.go index 9c5e532..9599b6a 100644 --- a/jsoniter_object_test.go +++ b/jsoniter_object_test.go @@ -3,8 +3,9 @@ package jsoniter import ( "bytes" "fmt" - "github.com/json-iterator/go/require" "testing" + + "github.com/json-iterator/go/require" ) func Test_empty_object(t *testing.T) { @@ -33,6 +34,7 @@ func Test_one_field(t *testing.T) { should.Equal("a", field) return true })) + } func Test_two_field(t *testing.T) { @@ -69,6 +71,11 @@ func Test_object_wrapper_any_get_all(t *testing.T) { } any := Wrap(TestObject{[]int{1, 2}, []int{3, 4}}) should.Contains(any.Get('*', 0).ToString(), `"Field2":3`) + should.Contains(any.Keys(), "Field1") + should.Contains(any.Keys(), "Field2") + should.NotContains(any.Keys(), "Field3") + + //should.Contains(any.GetObject()["Field1"].GetArray()[0], 1) } func Test_write_object(t *testing.T) { @@ -167,6 +174,106 @@ func Test_decode_five_fields_struct(t *testing.T) { should.Equal("e", obj.Field5) } +func Test_decode_six_fields_struct(t *testing.T) { + should := require.New(t) + type TestObject struct { + Field1 string + Field2 string + Field3 string + Field4 string + Field5 string + Field6 string + } + obj := TestObject{} + should.Nil(UnmarshalFromString(`{}`, &obj)) + should.Equal("", obj.Field1) + should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "b", "Field3": "c", "Field4": "d", "Field5": "e", "Field6": "x"}`, &obj)) + should.Equal("a", obj.Field1) + should.Equal("b", obj.Field2) + should.Equal("c", obj.Field3) + should.Equal("d", obj.Field4) + should.Equal("e", obj.Field5) + should.Equal("x", obj.Field6) +} + +func Test_decode_seven_fields_struct(t *testing.T) { + should := require.New(t) + type TestObject struct { + Field1 string + Field2 string + Field3 string + Field4 string + Field5 string + Field6 string + Field7 string + } + obj := TestObject{} + should.Nil(UnmarshalFromString(`{}`, &obj)) + should.Equal("", obj.Field1) + should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "b", "Field3": "c", "Field4": "d", "Field5": "e", "Field6": "x", "Field7":"y"}`, &obj)) + should.Equal("a", obj.Field1) + should.Equal("b", obj.Field2) + should.Equal("c", obj.Field3) + should.Equal("d", obj.Field4) + should.Equal("e", obj.Field5) + should.Equal("x", obj.Field6) + should.Equal("y", obj.Field7) +} + +func Test_decode_eight_fields_struct(t *testing.T) { + should := require.New(t) + type TestObject struct { + Field1 string + Field2 string + Field3 string + Field4 string + Field5 string + Field6 string + Field7 string + Field8 string + } + obj := TestObject{} + should.Nil(UnmarshalFromString(`{}`, &obj)) + should.Equal("", obj.Field1) + should.Nil(UnmarshalFromString(`{"Field8":"1", "Field1": "a", "Field2": "b", "Field3": "c", "Field4": "d", "Field5": "e", "Field6": "x", "Field7":"y"}`, &obj)) + should.Equal("a", obj.Field1) + should.Equal("b", obj.Field2) + should.Equal("c", obj.Field3) + should.Equal("d", obj.Field4) + should.Equal("e", obj.Field5) + should.Equal("x", obj.Field6) + should.Equal("y", obj.Field7) + should.Equal("1", obj.Field8) +} + +func Test_decode_nine_fields_struct(t *testing.T) { + should := require.New(t) + type TestObject struct { + Field1 string + Field2 string + Field3 string + Field4 string + Field5 string + Field6 string + Field7 string + Field8 string + Field9 string + } + obj := TestObject{} + should.Nil(UnmarshalFromString(`{}`, &obj)) + should.Equal("", obj.Field1) + should.Nil(UnmarshalFromString(`{"Field8" : "zzzzzzzzzzz", "Field7": "zz", "Field6" : "xx", "Field1": "a", "Field2": "b", "Field3": "c", "Field4": "d", "Field5": "e", "Field9":"f"}`, &obj)) + should.Equal("a", obj.Field1) + should.Equal("b", obj.Field2) + should.Equal("c", obj.Field3) + should.Equal("d", obj.Field4) + should.Equal("e", obj.Field5) + should.Equal("xx", obj.Field6) + should.Equal("zz", obj.Field7) + should.Equal("zzzzzzzzzzz", obj.Field8) + should.Equal("f", obj.Field9) +} + func Test_decode_ten_fields_struct(t *testing.T) { should := require.New(t) type TestObject struct { @@ -184,12 +291,44 @@ func Test_decode_ten_fields_struct(t *testing.T) { obj := TestObject{} should.Nil(UnmarshalFromString(`{}`, &obj)) should.Equal("", obj.Field1) - should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "b", "Field3": "c", "Field4": "d", "Field5": "e"}`, &obj)) + should.Nil(UnmarshalFromString(`{"Field10":"x", "Field9": "x", "Field8":"x", "Field7":"x", "Field6":"x", "Field1": "a", "Field2": "b", "Field3": "c", "Field4": "d", "Field5": "e"}`, &obj)) should.Equal("a", obj.Field1) should.Equal("b", obj.Field2) should.Equal("c", obj.Field3) should.Equal("d", obj.Field4) should.Equal("e", obj.Field5) + should.Equal("x", obj.Field6) + should.Equal("x", obj.Field7) + should.Equal("x", obj.Field8) + should.Equal("x", obj.Field9) + should.Equal("x", obj.Field10) +} + +func Test_decode_more_than_ten_fields_struct(t *testing.T) { + should := require.New(t) + type TestObject struct { + Field1 string + Field2 string + Field3 string + Field4 string + Field5 string + Field6 string + Field7 string + Field8 string + Field9 string + Field10 string + Field11 int + } + obj := TestObject{} + should.Nil(UnmarshalFromString(`{}`, &obj)) + should.Equal("", obj.Field1) + should.Nil(UnmarshalFromString(`{"Field11":1, "Field1": "a", "Field2": "b", "Field3": "c", "Field4": "d", "Field5": "e"}`, &obj)) + should.Equal("a", obj.Field1) + should.Equal("b", obj.Field2) + should.Equal("c", obj.Field3) + should.Equal("d", obj.Field4) + should.Equal("e", obj.Field5) + should.Equal(1, obj.Field11) } func Test_decode_struct_field_with_tag(t *testing.T) { @@ -381,7 +520,7 @@ func Test_shadow_struct_field(t *testing.T) { should.Contains(output, `"max_age":20`) } -func Test_embeded_order(t *testing.T) { +func Test_embedded_order(t *testing.T) { type A struct { Field2 string } diff --git a/jsoniter_skip_test.go b/jsoniter_skip_test.go index c789a98..1212f95 100644 --- a/jsoniter_skip_test.go +++ b/jsoniter_skip_test.go @@ -3,8 +3,9 @@ package jsoniter import ( "bytes" "encoding/json" - "github.com/json-iterator/go/require" "testing" + + "github.com/json-iterator/go/require" ) func Test_skip_number(t *testing.T) { @@ -15,6 +16,7 @@ func Test_skip_number(t *testing.T) { if iter.ReadString() != "b" { t.FailNow() } + } func Test_skip_null(t *testing.T) { diff --git a/jsoniter_wrap_test.go b/jsoniter_wrap_test.go new file mode 100644 index 0000000..117a0e2 --- /dev/null +++ b/jsoniter_wrap_test.go @@ -0,0 +1,118 @@ +package jsoniter + +import ( + "testing" + + "github.com/json-iterator/go/require" +) + +func Test_wrap_and_valuetype_everything(t *testing.T) { + should := require.New(t) + var i interface{} + any := Get([]byte("123")) + // default of number type is float64 + i = float64(123) + should.Equal(i, any.GetInterface()) + + any = Wrap(int8(10)) + should.Equal(any.ValueType(), Number) + should.Equal(any.LastError(), nil) + // get interface is not int8 interface + // i = int8(10) + // should.Equal(i, any.GetInterface()) + + any = Wrap(int16(10)) + should.Equal(any.ValueType(), Number) + should.Equal(any.LastError(), nil) + //i = int16(10) + //should.Equal(i, any.GetInterface()) + + any = Wrap(int32(10)) + should.Equal(any.ValueType(), Number) + should.Equal(any.LastError(), nil) + i = int32(10) + should.Equal(i, any.GetInterface()) + any = Wrap(int64(10)) + should.Equal(any.ValueType(), Number) + should.Equal(any.LastError(), nil) + i = int64(10) + should.Equal(i, any.GetInterface()) + + any = Wrap(uint(10)) + should.Equal(any.ValueType(), Number) + should.Equal(any.LastError(), nil) + // not equal + //i = uint(10) + //should.Equal(i, any.GetInterface()) + any = Wrap(uint8(10)) + should.Equal(any.ValueType(), Number) + should.Equal(any.LastError(), nil) + // not equal + // i = uint8(10) + // should.Equal(i, any.GetInterface()) + any = Wrap(uint16(10)) + should.Equal(any.ValueType(), Number) + should.Equal(any.LastError(), nil) + any = Wrap(uint32(10)) + should.Equal(any.ValueType(), Number) + should.Equal(any.LastError(), nil) + i = uint32(10) + should.Equal(i, any.GetInterface()) + any = Wrap(uint64(10)) + should.Equal(any.ValueType(), Number) + should.Equal(any.LastError(), nil) + i = uint64(10) + should.Equal(i, any.GetInterface()) + + any = Wrap(float32(10)) + should.Equal(any.ValueType(), Number) + should.Equal(any.LastError(), nil) + // not equal + //i = float32(10) + //should.Equal(i, any.GetInterface()) + any = Wrap(float64(10)) + should.Equal(any.ValueType(), Number) + should.Equal(any.LastError(), nil) + i = float64(10) + should.Equal(i, any.GetInterface()) + + any = Wrap(true) + should.Equal(any.ValueType(), Bool) + should.Equal(any.LastError(), nil) + i = true + should.Equal(i, any.GetInterface()) + any = Wrap(false) + should.Equal(any.ValueType(), Bool) + should.Equal(any.LastError(), nil) + i = false + should.Equal(i, any.GetInterface()) + + any = Wrap(nil) + should.Equal(any.ValueType(), Nil) + should.Equal(any.LastError(), nil) + i = nil + should.Equal(i, any.GetInterface()) + + stream := NewStream(ConfigDefault, nil, 32) + any.WriteTo(stream) + should.Equal("null", string(stream.Buffer())) + should.Equal(any.LastError(), nil) + + any = Wrap(struct{ age int }{age: 1}) + should.Equal(any.ValueType(), Object) + should.Equal(any.LastError(), nil) + i = struct{ age int }{age: 1} + should.Equal(i, any.GetInterface()) + + any = Wrap(map[string]interface{}{"abc": 1}) + should.Equal(any.ValueType(), Object) + should.Equal(any.LastError(), nil) + i = map[string]interface{}{"abc": 1} + should.Equal(i, any.GetInterface()) + + any = Wrap("abc") + i = "abc" + should.Equal(i, any.GetInterface()) + should.Equal(nil, any.LastError()) + +}