1
0
mirror of https://github.com/json-iterator/go.git synced 2024-11-24 08:22:14 +02:00

remove any

This commit is contained in:
Tao Wen 2017-01-22 19:36:19 +08:00
parent 9c2b1d24b3
commit 9df37bbd68
7 changed files with 1 additions and 703 deletions

View File

@ -1,72 +0,0 @@
package jsoniter
import (
"fmt"
"testing"
)
func Test_get_from_map(t *testing.T) {
any := Any{val: map[string]interface{}{
"hello": "world",
}}
if any.ToString("hello") != "world" {
t.FailNow()
}
}
func Test_get_from_array(t *testing.T) {
any := Any{val: []interface{}{
"hello", "world",
}}
if any.ToString(1) != "world" {
t.FailNow()
}
}
func Test_get_int(t *testing.T) {
any := Any{val: []interface{}{
1, 2, 3,
}}
if any.ToInt(1) != 2 {
t.FailNow()
}
}
func Test_is_null(t *testing.T) {
any := Any{val: []interface{}{
1, 2, 3,
}}
if any.IsNil() != false {
t.FailNow()
}
}
func Test_get_bool(t *testing.T) {
any := Any{val: []interface{}{
true, true, false,
}}
if any.ToBool(1) != true {
t.FailNow()
}
}
func Test_nested_read(t *testing.T) {
any := Any{val: []interface{}{
true, map[string]interface{}{
"hello": "world",
}, false,
}}
if any.ToString(1, "hello") != "world" {
fmt.Println(any.Error)
t.FailNow()
}
}
func Test_int_to_string(t *testing.T) {
any := Any{val: []interface{}{
true, 5, false,
}}
if any.ToString(1) != "5" {
t.FailNow()
}
}

View File

@ -1,445 +0,0 @@
package jsoniter
import (
"fmt"
"reflect"
"strconv"
)
// Any API is for maximum flexibility
type Any struct {
val interface{}
Error error
LastAccessed interface{}
}
// MakeAny creates Any instance
func MakeAny(val interface{}) *Any {
return &Any{val, nil, nil}
}
// Get extracts a json object from Any
func (any *Any) Get(keys ...interface{}) interface{} {
ret, err := getPath(any.val, keys...)
any.LastAccessed = ret
if err != nil {
any.Error = err
return ""
}
return ret
}
// GetValueType gets type of a value
func (any *Any) GetValueType(keys ...interface{}) ValueType {
ret, err := getPath(any.val, keys...)
any.LastAccessed = ret
if err != nil {
any.Error = err
return Invalid
}
switch reflect.TypeOf(ret).Kind() {
case reflect.Uint8:
return Number
case reflect.Int8:
return Number
case reflect.Uint16:
return Number
case reflect.Int16:
return Number
case reflect.Uint32:
return Number
case reflect.Int32:
return Number
case reflect.Uint64:
return Number
case reflect.Int64:
return Number
case reflect.Int:
return Number
case reflect.Uint:
return Number
case reflect.Float32:
return Number
case reflect.Float64:
return Number
case reflect.String:
return String
case reflect.Bool:
return Bool
case reflect.Array:
return Array
case reflect.Struct:
return Object
default:
return Invalid
}
}
// ToString converts a json object to string
func (any *Any) ToString(keys ...interface{}) string {
ret, err := getPath(any.val, keys...)
any.LastAccessed = ret
if err != nil {
any.Error = err
return ""
}
switch ret := ret.(type) {
case uint8:
return strconv.FormatInt(int64(ret), 10)
case int8:
return strconv.FormatInt(int64(ret), 10)
case uint16:
return strconv.FormatInt(int64(ret), 10)
case int16:
return strconv.FormatInt(int64(ret), 10)
case uint32:
return strconv.FormatInt(int64(ret), 10)
case int32:
return strconv.FormatInt(int64(ret), 10)
case uint64:
return strconv.FormatUint(uint64(ret), 10)
case int64:
return strconv.FormatInt(int64(ret), 10)
case int:
return strconv.FormatInt(int64(ret), 10)
case uint:
return strconv.FormatInt(int64(ret), 10)
case float32:
return strconv.FormatFloat(float64(ret), 'E', -1, 32)
case float64:
return strconv.FormatFloat(ret, 'E', -1, 64)
case string:
return ret
default:
return fmt.Sprintf("%v", ret)
}
}
// ToUint8 converts a json object to Uint8
func (any *Any) ToUint8(keys ...interface{}) uint8 {
ret, err := getPathAsInt64(any, keys...)
if err != nil {
any.Error = err
return 0
}
return uint8(ret)
}
// ToInt8 converts a json object to Int8
func (any *Any) ToInt8(keys ...interface{}) int8 {
ret, err := getPathAsInt64(any, keys...)
if err != nil {
any.Error = err
return 0
}
return int8(ret)
}
// ToUint16 converts a json object to Uint16
func (any *Any) ToUint16(keys ...interface{}) uint16 {
ret, err := getPathAsInt64(any, keys...)
if err != nil {
any.Error = err
return 0
}
return uint16(ret)
}
// ToInt16 converts a json object to Int16
func (any *Any) ToInt16(keys ...interface{}) int16 {
ret, err := getPathAsInt64(any, keys...)
if err != nil {
any.Error = err
return 0
}
return int16(ret)
}
// ToUint32 converts a json object to Uint32
func (any *Any) ToUint32(keys ...interface{}) uint32 {
ret, err := getPathAsInt64(any, keys...)
if err != nil {
any.Error = err
return 0
}
return uint32(ret)
}
// ToInt32 converts a json object to Int32
func (any *Any) ToInt32(keys ...interface{}) int32 {
ret, err := getPathAsInt64(any, keys...)
if err != nil {
any.Error = err
return 0
}
return int32(ret)
}
// ToUint64 converts a json object to Uint64
func (any *Any) ToUint64(keys ...interface{}) uint64 {
ret, err := getPathAsUint64(any, keys...)
if err != nil {
any.Error = err
return 0
}
return uint64(ret)
}
// ToInt64 converts a json object to Int64
func (any *Any) ToInt64(keys ...interface{}) int64 {
ret, err := getPathAsInt64(any, keys...)
if err != nil {
any.Error = err
return 0
}
return int64(ret)
}
// ToInt converts a json object to Int
func (any *Any) ToInt(keys ...interface{}) int {
ret, err := getPathAsInt64(any, keys...)
if err != nil {
any.Error = err
return 0
}
return int(ret)
}
// ToUint converts a json object to Uint
func (any *Any) ToUint(keys ...interface{}) uint {
ret, err := getPathAsInt64(any, keys...)
if err != nil {
any.Error = err
return 0
}
return uint(ret)
}
// ToFloat32 converts a json object to Float32
func (any *Any) ToFloat32(keys ...interface{}) float32 {
ret, err := getPathAsFloat64(any, keys...)
if err != nil {
any.Error = err
return 0
}
return float32(ret)
}
// ToFloat64 converts a json object to Float64
func (any *Any) ToFloat64(keys ...interface{}) float64 {
ret, err := getPathAsFloat64(any, keys...)
if err != nil {
any.Error = err
return 0
}
return ret
}
// ToBool converts a json object to Bool
func (any *Any) ToBool(keys ...interface{}) bool {
ret, err := getPath(any.val, keys...)
any.LastAccessed = ret
if err != nil {
any.Error = err
return false
}
typedRet, ok := ret.(bool)
if !ok {
any.Error = fmt.Errorf("%v is not bool", ret)
return false
}
return typedRet
}
// IsNil judges whether a json object is nil
func (any *Any) IsNil(keys ...interface{}) bool {
ret, err := getPath(any.val, keys...)
any.LastAccessed = ret
if err != nil {
any.Error = err
return false
}
return reflect.ValueOf(ret).IsNil()
}
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) {
case uint8:
return int64(ret), nil
case int8:
return int64(ret), nil
case uint16:
return int64(ret), nil
case int16:
return int64(ret), nil
case uint32:
return int64(ret), nil
case int32:
return int64(ret), nil
case uint64:
return int64(ret), nil
case int64:
return int64(ret), nil
case int:
return int64(ret), nil
case uint:
return int64(ret), nil
case float32:
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(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) {
case uint8:
return uint64(ret), nil
case int8:
return uint64(ret), nil
case uint16:
return uint64(ret), nil
case int16:
return uint64(ret), nil
case uint32:
return uint64(ret), nil
case int32:
return uint64(ret), nil
case uint64:
return uint64(ret), nil
case int64:
return uint64(ret), nil
case int:
return uint64(ret), nil
case uint:
return uint64(ret), nil
case float32:
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(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) {
case uint8:
return float64(ret), nil
case int8:
return float64(ret), nil
case uint16:
return float64(ret), nil
case int16:
return float64(ret), nil
case uint32:
return float64(ret), nil
case int32:
return float64(ret), nil
case uint64:
return float64(ret), nil
case int64:
return float64(ret), nil
case int:
return float64(ret), nil
case uint:
return float64(ret), nil
case float32:
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)
}
}
func getPath(val interface{}, keys ...interface{}) (interface{}, error) {
if len(keys) == 0 {
return val, nil
}
switch key := keys[0].(type) {
case string:
nextVal, err := getFromMap(val, key)
if err != nil {
return nil, err
}
nextKeys := make([]interface{}, len(keys)-1)
copy(nextKeys, keys[1:])
return getPath(nextVal, nextKeys...)
case int:
nextVal, err := getFromArray(val, key)
if err != nil {
return nil, err
}
nextKeys := make([]interface{}, len(keys)-1)
copy(nextKeys, keys[1:])
return getPath(nextVal, nextKeys...)
default:
return nil, fmt.Errorf("%v is not string or int", keys[0])
}
}
func getFromMap(val interface{}, key string) (interface{}, error) {
mapVal, ok := val.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("%v is not map[string]interface{}", val)
}
ret, found := mapVal[key]
if !found {
return nil, fmt.Errorf("%v not found in %v", key, mapVal)
}
return ret, nil
}
func getFromArray(val interface{}, key int) (interface{}, error) {
arrayVal, ok := val.([]interface{})
if !ok {
return nil, fmt.Errorf("%v is not []interface{}", val)
}
if key >= len(arrayVal) {
return nil, fmt.Errorf("%v exceed %v", key, arrayVal)
}
if key < 0 {
return nil, fmt.Errorf("%v exceed %v", key, arrayVal)
}
return arrayVal[key], nil
}

View File

@ -2,9 +2,7 @@ package jsoniter
import (
"fmt"
"io"
"reflect"
"strconv"
"sync/atomic"
"unsafe"
)
@ -200,108 +198,6 @@ type emptyInterface struct {
word unsafe.Pointer
}
// ReadAny converts a json object in a Iterator instance to Any
func (iter *Iterator) ReadAny() (ret *Any) {
valueType := iter.WhatIsNext()
switch valueType {
case String:
return MakeAny(iter.ReadString())
case Number:
return iter.readNumber()
case Nil:
return MakeAny(nil)
case Bool:
return MakeAny(iter.ReadBool())
case Array:
val := []interface{}{}
for iter.ReadArray() {
element := iter.ReadAny()
if iter.Error != nil {
return
}
val = append(val, element.val)
}
return MakeAny(val)
case Object:
val := map[string]interface{}{}
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
element := iter.ReadAny()
if iter.Error != nil {
return
}
val[string([]byte(field))] = element.val
}
return MakeAny(val)
default:
iter.reportError("ReadAny", fmt.Sprintf("unexpected value type: %v", valueType))
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:
iter.head = i
hasMore = false
break
}
if !hasMore {
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)
}
// Read converts an Iterator instance into go interface, same as json.Unmarshal
func (iter *Iterator) ReadVal(obj interface{}) {
typ := reflect.TypeOf(obj)
@ -365,9 +261,6 @@ func (p prefix) addToEncoder(encoder Encoder, err error) (Encoder, error) {
func decoderOfType(typ reflect.Type) (Decoder, error) {
typeName := typ.String()
if typeName == "jsoniter.Any" {
return &anyDecoder{}, nil
}
typeDecoder := typeDecoders[typeName]
if typeDecoder != nil {
return typeDecoder, nil

View File

@ -160,20 +160,13 @@ type interfaceCodec struct {
}
func (codec *interfaceCodec) decode(ptr unsafe.Pointer, iter *Iterator) {
*((*interface{})(ptr)) = iter.ReadAny().Get()
*((*interface{})(ptr)) = iter.Read()
}
func (codec *interfaceCodec) encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteVal(*((*interface{})(ptr)))
}
type anyDecoder struct {
}
func (decoder *anyDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
*((*Any)(ptr)) = *iter.ReadAny()
}
type stringNumberDecoder struct {
elemDecoder Decoder
}

View File

@ -1,42 +0,0 @@
package jsoniter
import (
"fmt"
"testing"
)
func Test_read_string_as_any(t *testing.T) {
iter := ParseString(`[1, {"hello": "world"}, 2]`)
any := iter.ReadAny()
if iter.Error != nil {
t.Fatal(iter.Error)
}
if any.ToString(1, "hello") != "world" {
t.FailNow()
}
}
func Test_read_float64_as_any(t *testing.T) {
iter := ParseString(`1.23`)
any := iter.ReadAny()
if any.ToFloat32() != 1.23 {
t.FailNow()
}
}
func Test_read_int_as_any(t *testing.T) {
iter := ParseString(`123`)
any := iter.ReadAny()
if any.ToFloat32() != 123 {
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()
}
}

View File

@ -12,12 +12,6 @@ func Test_bind_api_demo(t *testing.T) {
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
@ -27,17 +21,6 @@ func Test_iterator_api_demo(t *testing.T) {
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.ReadVal(&abc)
fmt.Println(abc.a.Get("b", "c"))
}
type User struct {
userID int
name string

View File

@ -1,8 +1,6 @@
package jsoniter
import (
"fmt"
"reflect"
"testing"
"github.com/json-iterator/go/require"
)
@ -26,16 +24,6 @@ func Test_read_map_of_interface(t *testing.T) {
should.Equal(map[string]interface{}{"hello": "world"}, iter.Read())
}
func Test_read_map_of_any(t *testing.T) {
iter := ParseString(`{"hello": "world"}`)
m := map[string]Any{"1": *MakeAny("2")}
iter.ReadVal(&m)
if !reflect.DeepEqual(map[string]Any{"1": *MakeAny("2"), "hello": *MakeAny("world")}, m) {
fmt.Println(iter.Error)
t.Fatal(m)
}
}
func Test_write_val_map(t *testing.T) {
should := require.New(t)
val := map[string]string{"1": "2"}