Tao Wen vor 9 Jahren
Ursprung
Commit
3e47c79b7e
6 geänderte Dateien mit 190 neuen und 80 gelöschten Zeilen
  1. 50 20
      any.go
  2. 0 28
      jsoniter.go
  3. 13 1
      jsoniter_any_test.go
  4. 56 0
      jsoniter_demo_test.go
  5. 2 2
      jsoniter_map_test.go
  6. 69 29
      jsoniter_reflect.go

+ 50 - 20
any.go

@@ -9,14 +9,16 @@ import (
 type Any struct {
 	val   interface{}
 	Error error
+	LastAccessed interface{}
 }
 
-func any(val interface{}) Any {
-	return Any{val, nil}
+func MakeAny(val interface{}) *Any {
+	return &Any{val, nil, nil}
 }
 
 func (any *Any) Get(keys ...interface{}) interface{} {
 	ret, err := getPath(any.val, keys...)
+	any.LastAccessed = ret
 	if err != nil {
 		any.Error = err
 		return "";
@@ -26,6 +28,7 @@ func (any *Any) Get(keys ...interface{}) interface{} {
 
 func (any *Any) GetValueType(keys ...interface{}) ValueType {
 	ret, err := getPath(any.val, keys...)
+	any.LastAccessed = ret
 	if err != nil {
 		any.Error = err
 		return Invalid;
@@ -71,6 +74,7 @@ func (any *Any) GetValueType(keys ...interface{}) ValueType {
 
 func (any *Any) ToString(keys ...interface{}) string {
 	ret, err := getPath(any.val, keys...)
+	any.LastAccessed = ret
 	if err != nil {
 		any.Error = err
 		return "";
@@ -108,7 +112,7 @@ func (any *Any) ToString(keys ...interface{}) string {
 }
 
 func (any *Any) ToUint8(keys ...interface{}) uint8 {
-	ret, err := getPathAsInt64(any.val, keys...)
+	ret, err := getPathAsInt64(any, keys...)
 	if err != nil {
 		any.Error = err
 		return 0;
@@ -117,7 +121,7 @@ func (any *Any) ToUint8(keys ...interface{}) uint8 {
 }
 
 func (any *Any) ToInt8(keys ...interface{}) int8 {
-	ret, err := getPathAsInt64(any.val, keys...)
+	ret, err := getPathAsInt64(any, keys...)
 	if err != nil {
 		any.Error = err
 		return 0;
@@ -126,7 +130,7 @@ func (any *Any) ToInt8(keys ...interface{}) int8 {
 }
 
 func (any *Any) ToUint16(keys ...interface{}) uint16 {
-	ret, err := getPathAsInt64(any.val, keys...)
+	ret, err := getPathAsInt64(any, keys...)
 	if err != nil {
 		any.Error = err
 		return 0;
@@ -135,7 +139,7 @@ func (any *Any) ToUint16(keys ...interface{}) uint16 {
 }
 
 func (any *Any) ToInt16(keys ...interface{}) int16 {
-	ret, err := getPathAsInt64(any.val, keys...)
+	ret, err := getPathAsInt64(any, keys...)
 	if err != nil {
 		any.Error = err
 		return 0;
@@ -144,7 +148,7 @@ func (any *Any) ToInt16(keys ...interface{}) int16 {
 }
 
 func (any *Any) ToUint32(keys ...interface{}) uint32 {
-	ret, err := getPathAsInt64(any.val, keys...)
+	ret, err := getPathAsInt64(any, keys...)
 	if err != nil {
 		any.Error = err
 		return 0;
@@ -153,7 +157,7 @@ func (any *Any) ToUint32(keys ...interface{}) uint32 {
 }
 
 func (any *Any) ToInt32(keys ...interface{}) int32 {
-	ret, err := getPathAsInt64(any.val, keys...)
+	ret, err := getPathAsInt64(any, keys...)
 	if err != nil {
 		any.Error = err
 		return 0;
@@ -162,7 +166,7 @@ func (any *Any) ToInt32(keys ...interface{}) int32 {
 }
 
 func (any *Any) ToUint64(keys ...interface{}) uint64 {
-	ret, err := getPathAsUint64(any.val, keys...)
+	ret, err := getPathAsUint64(any, keys...)
 	if err != nil {
 		any.Error = err
 		return 0;
@@ -171,7 +175,7 @@ func (any *Any) ToUint64(keys ...interface{}) uint64 {
 }
 
 func (any *Any) ToInt64(keys ...interface{}) int64 {
-	ret, err := getPathAsInt64(any.val, keys...)
+	ret, err := getPathAsInt64(any, keys...)
 	if err != nil {
 		any.Error = err
 		return 0;
@@ -180,7 +184,7 @@ func (any *Any) ToInt64(keys ...interface{}) int64 {
 }
 
 func (any *Any) ToInt(keys ...interface{}) int {
-	ret, err := getPathAsInt64(any.val, keys...)
+	ret, err := getPathAsInt64(any, keys...)
 	if err != nil {
 		any.Error = err
 		return 0;
@@ -189,7 +193,7 @@ func (any *Any) ToInt(keys ...interface{}) int {
 }
 
 func (any *Any) ToUint(keys ...interface{}) uint {
-	ret, err := getPathAsInt64(any.val, keys...)
+	ret, err := getPathAsInt64(any, keys...)
 	if err != nil {
 		any.Error = err
 		return 0;
@@ -198,7 +202,7 @@ func (any *Any) ToUint(keys ...interface{}) uint {
 }
 
 func (any *Any) ToFloat32(keys ...interface{}) float32 {
-	ret, err := getPathAsFloat64(any.val, keys...)
+	ret, err := getPathAsFloat64(any, keys...)
 	if err != nil {
 		any.Error = err
 		return 0;
@@ -207,7 +211,7 @@ func (any *Any) ToFloat32(keys ...interface{}) float32 {
 }
 
 func (any *Any) ToFloat64(keys ...interface{}) float64 {
-	ret, err := getPathAsFloat64(any.val, keys...)
+	ret, err := getPathAsFloat64(any, keys...)
 	if err != nil {
 		any.Error = err
 		return 0;
@@ -217,6 +221,7 @@ func (any *Any) ToFloat64(keys ...interface{}) float64 {
 
 func (any *Any) ToBool(keys ...interface{}) bool {
 	ret, err := getPath(any.val, keys...)
+	any.LastAccessed = ret
 	if err != nil {
 		any.Error = err
 		return false;
@@ -231,6 +236,7 @@ func (any *Any) ToBool(keys ...interface{}) bool {
 
 func (any *Any) IsNull(keys ...interface{}) bool {
 	ret, err := getPath(any.val, keys...)
+	any.LastAccessed = ret
 	if err != nil {
 		any.Error = err
 		return false;
@@ -238,9 +244,11 @@ func (any *Any) IsNull(keys ...interface{}) bool {
 	return reflect.ValueOf(ret).IsNil()
 }
 
-func getPathAsInt64(val interface{}, keys ...interface{}) (int64, error) {
-	ret, err := getPath(val, keys...)
+func getPathAsInt64(any *Any, keys ...interface{}) (int64, error) {
+	ret, err := getPath(any.val, keys...)
+	any.LastAccessed = ret
 	if err != nil {
+		any.Error = err
 		return 0, err
 	}
 	switch ret := ret.(type) {
@@ -268,14 +276,22 @@ func getPathAsInt64(val interface{}, keys ...interface{}) (int64, error) {
 		return int64(ret), nil;
 	case float64:
 		return int64(ret), nil;
+	case string:
+		intVal, err := strconv.ParseInt(ret, 10, 64)
+		if err != nil {
+			return 0, err
+		}
+		return intVal, nil;
 	default:
 		return 0, fmt.Errorf("%v is not number", ret)
 	}
 }
 
-func getPathAsUint64(val interface{}, keys ...interface{}) (uint64, error) {
-	ret, err := getPath(val, keys...)
+func getPathAsUint64(any *Any, keys ...interface{}) (uint64, error) {
+	ret, err := getPath(any.val, keys...)
+	any.LastAccessed = ret
 	if err != nil {
+		any.Error = err
 		return 0, err
 	}
 	switch ret := ret.(type) {
@@ -303,14 +319,22 @@ func getPathAsUint64(val interface{}, keys ...interface{}) (uint64, error) {
 		return uint64(ret), nil;
 	case float64:
 		return uint64(ret), nil;
+	case string:
+		intVal, err := strconv.ParseUint(ret, 10, 64)
+		if err != nil {
+			return 0, err
+		}
+		return intVal, nil;
 	default:
 		return 0, fmt.Errorf("%v is not number", ret)
 	}
 }
 
-func getPathAsFloat64(val interface{}, keys ...interface{}) (float64, error) {
-	ret, err := getPath(val, keys...)
+func getPathAsFloat64(any *Any, keys ...interface{}) (float64, error) {
+	ret, err := getPath(any.val, keys...)
+	any.LastAccessed = ret
 	if err != nil {
+		any.Error = err
 		return 0, err
 	}
 	switch ret := ret.(type) {
@@ -338,6 +362,12 @@ func getPathAsFloat64(val interface{}, keys ...interface{}) (float64, error) {
 		return float64(ret), nil;
 	case float64:
 		return float64(ret), nil;
+	case string:
+		floatVal, err := strconv.ParseFloat(ret, 64)
+		if err != nil {
+			return 0, err
+		}
+		return floatVal, nil;
 	default:
 		return 0, fmt.Errorf("%v is not number", ret)
 	}

+ 0 - 28
jsoniter.go

@@ -670,34 +670,6 @@ func (iter *Iterator) ReadFloat32() (ret float32) {
 	return float32(val)
 }
 
-func (iter *Iterator) ReadNumber() (ret string) {
-	strBuf := [8]byte{}
-	str := strBuf[0:0]
-	hasMore := true
-	for(hasMore) {
-		for i := iter.head; i < iter.tail; i++ {
-			c := iter.buf[i]
-			switch c {
-			case '-', '+', '.', 'e', 'E', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
-				str = append(str, c)
-				continue
-			default:
-				hasMore = false
-				break
-			}
-		}
-		if hasMore {
-			if !iter.loadMore() {
-				break
-			}
-		}
-	}
-	if iter.Error != nil && iter.Error != io.EOF {
-		return
-	}
-	return string(str)
-}
-
 func (iter *Iterator) ReadFloat64() (ret float64) {
 	strBuf := [8]byte{}
 	str := strBuf[0:0]

+ 13 - 1
jsoniter_any_test.go

@@ -1,6 +1,9 @@
 package jsoniter
 
-import "testing"
+import (
+	"testing"
+	"fmt"
+)
 
 func Test_read_string_as_any(t *testing.T) {
 	iter := ParseString(`[1, {"hello": "world"}, 2]`)
@@ -25,3 +28,12 @@ func Test_read_int_as_any(t *testing.T) {
 		t.FailNow()
 	}
 }
+
+func Test_read_any_from_nested(t *testing.T) {
+	iter := ParseString(`{"numbers": ["1", "2", ["3", "4"]]}`)
+	val := iter.ReadAny()
+	if val.ToInt("numbers", 2, 0) != 3 {
+		fmt.Println(val.Error)
+		t.FailNow()
+	}
+}

+ 56 - 0
jsoniter_demo_test.go

@@ -0,0 +1,56 @@
+package jsoniter
+
+import (
+	"testing"
+	"fmt"
+)
+
+func Test_bind_api_demo(t *testing.T) {
+	iter := ParseString(`[0,1,2,3]`)
+	val := []int{}
+	iter.Read(&val)
+	fmt.Println(val[3])
+}
+
+func Test_any_api_demo(t *testing.T) {
+	iter := ParseString(`[0,1,2,3]`)
+	val := iter.ReadAny()
+	fmt.Println(val.Get(3))
+}
+
+func Test_iterator_api_demo(t *testing.T) {
+	iter := ParseString(`[0,1,2,3]`)
+	total := 0
+	for iter.ReadArray() {
+		total += iter.ReadInt()
+	}
+	fmt.Println(total)
+}
+
+type ABC struct {
+	a Any
+}
+
+func Test_deep_nested_any_api(t *testing.T) {
+	iter := ParseString(`{"a": {"b": {"c": "d"}}}`)
+	abc := &ABC{}
+	iter.Read(&abc)
+	fmt.Println(abc.a.Get("b", "c"))
+}
+
+type User struct {
+	userId int
+	name string
+	tags []string
+}
+
+func Test_iterator_and_bind_api(t *testing.T) {
+	iter := ParseString(`[123, {"name": "taowen", "tags": ["crazy", "hacker"]}]`)
+	user := User{}
+	iter.ReadArray()
+	user.userId = iter.ReadInt()
+	iter.ReadArray()
+	iter.Read(&user)
+	iter.ReadArray() // array end
+	fmt.Println(user)
+}

+ 2 - 2
jsoniter_map_test.go

@@ -28,9 +28,9 @@ func Test_read_map_of_interface(t *testing.T) {
 
 func Test_read_map_of_any(t *testing.T) {
 	iter := ParseString(`{"hello": "world"}`)
-	m := map[string]Any{"1": any("2")}
+	m := map[string]Any{"1": *MakeAny("2")}
 	iter.Read(&m)
-	if !reflect.DeepEqual(map[string]Any{"1": any("2"), "hello": any("world")}, m) {
+	if !reflect.DeepEqual(map[string]Any{"1": *MakeAny("2"), "hello": *MakeAny("world")}, m) {
 		fmt.Println(iter.Error)
 		t.Fatal(m)
 	}

+ 69 - 29
jsoniter_reflect.go

@@ -490,35 +490,13 @@ func (iter *Iterator) ReadAny() (ret *Any) {
 	valueType := iter.WhatIsNext()
 	switch valueType {
 	case String:
-		return &Any{iter.ReadString(), nil}
+		return MakeAny(iter.ReadString())
 	case Number:
-		number := iter.ReadNumber()
-		if strings.Contains(number, ".") {
-			val, err := strconv.ParseFloat(number, 64)
-			if err != nil {
-				iter.Error = err
-				return
-			}
-			return &Any{val, nil}
-		}
-		if strings.HasPrefix(number, "-") {
-			val, err := strconv.ParseUint(number, 10, 64)
-			if err != nil {
-				iter.Error = err
-				return
-			}
-			return &Any{val, nil}
-		}
-		val, err := strconv.ParseInt(number, 10, 64)
-		if err != nil {
-			iter.Error = err
-			return
-		}
-		return &Any{val, nil}
+		return iter.readNumber()
 	case Null:
-		return &Any{nil, nil}
+		return MakeAny(nil)
 	case Bool:
-		return &Any{iter.ReadBool(), nil}
+		return MakeAny(iter.ReadBool())
 	case Array:
 		val := []interface{}{}
 		for (iter.ReadArray()) {
@@ -528,7 +506,7 @@ func (iter *Iterator) ReadAny() (ret *Any) {
 			}
 			val = append(val, element.val)
 		}
-		return &Any{val, nil}
+		return MakeAny(val)
 	case Object:
 		val := map[string]interface{}{}
 		for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
@@ -538,11 +516,73 @@ func (iter *Iterator) ReadAny() (ret *Any) {
 			}
 			val[field] = element.val
 		}
-		return &Any{val, nil}
+		return MakeAny(val)
 	default:
 		iter.ReportError("ReadAny", fmt.Sprintf("unexpected value type: %v", valueType))
-		return nil
+		return MakeAny(nil)
+	}
+}
+
+
+
+func (iter *Iterator) readNumber() (ret *Any) {
+	strBuf := [8]byte{}
+	str := strBuf[0:0]
+	hasMore := true
+	foundFloat := false
+	foundNegative := false
+	for(hasMore) {
+		for i := iter.head; i < iter.tail; i++ {
+			c := iter.buf[i]
+			switch c {
+			case '-':
+				foundNegative = true
+				str = append(str, c)
+				continue
+			case '+', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+				str = append(str, c)
+				continue
+			case '.', 'e', 'E':
+				foundFloat = true
+				str = append(str, c)
+				continue
+			default:
+				hasMore = false
+				break
+			}
+		}
+		if hasMore {
+			if !iter.loadMore() {
+				break
+			}
+		}
+	}
+	if iter.Error != nil && iter.Error != io.EOF {
+		return
+	}
+	number := *(*string)(unsafe.Pointer(&str))
+	if foundFloat {
+		val, err := strconv.ParseFloat(number, 64)
+		if err != nil {
+			iter.Error = err
+			return
+		}
+		return MakeAny(val)
+	}
+	if foundNegative {
+		val, err := strconv.ParseInt(number, 10, 64)
+		if err != nil {
+			iter.Error = err
+			return
+		}
+		return MakeAny(val)
+	}
+	val, err := strconv.ParseUint(number, 10, 64)
+	if err != nil {
+		iter.Error = err
+		return
 	}
+	return MakeAny(val)
 }
 
 func (iter *Iterator) Read(obj interface{}) {