1
0
mirror of https://github.com/json-iterator/go.git synced 2025-04-20 11:28:49 +02:00

Any Get will never return nil

This commit is contained in:
Tao Wen 2017-01-26 16:24:01 +08:00
parent 9abc2f52b0
commit 85edb698c8
12 changed files with 106 additions and 13 deletions

View File

@ -1,7 +1,10 @@
package jsoniter package jsoniter
import "fmt"
type Any interface { type Any interface {
LastError() error LastError() error
ValueType() ValueType
ToBool() bool ToBool() bool
ToInt() int ToInt() int
ToInt32() int32 ToInt32() int32
@ -26,7 +29,7 @@ type Any interface {
type baseAny struct{} type baseAny struct{}
func (any *baseAny) Get(path ...interface{}) Any { func (any *baseAny) Get(path ...interface{}) Any {
return &invalidAny{} return &invalidAny{baseAny{}, fmt.Errorf("Get %v from simple value", path)}
} }
func (any *baseAny) Size() int { func (any *baseAny) Size() int {

View File

@ -2,6 +2,7 @@ package jsoniter
import ( import (
"unsafe" "unsafe"
"fmt"
) )
type arrayLazyAny struct { type arrayLazyAny struct {
@ -13,6 +14,10 @@ type arrayLazyAny struct {
remaining []byte remaining []byte
} }
func (any *arrayLazyAny) ValueType() ValueType {
return Array
}
func (any *arrayLazyAny) Parse() *Iterator { func (any *arrayLazyAny) Parse() *Iterator {
iter := any.iter iter := any.iter
if iter == nil { if iter == nil {
@ -176,12 +181,20 @@ func (any *arrayLazyAny) Get(path ...interface{}) Any {
if len(path) == 0 { if len(path) == 0 {
return any return any
} }
if len(path) == 1 { var element Any
idx := path[0].(int) idx, ok := path[0].(int)
return any.fillCacheUntil(idx) if ok {
element = any.fillCacheUntil(idx)
if element == nil {
element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", idx, any.cache)}
}
} else { } else {
idx := path[0].(int) element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", idx, any.cache)}
return any.fillCacheUntil(idx).Get(path[1:]...) }
if len(path) == 1 {
return element
} else {
return element.Get(path[1:]...)
} }
} }

View File

@ -48,6 +48,10 @@ func (any *trueAny) GetInterface() interface{} {
return true return true
} }
func (any *trueAny) ValueType() ValueType {
return Bool
}
type falseAny struct { type falseAny struct {
baseAny baseAny
} }
@ -95,3 +99,7 @@ func (any *falseAny) Parse() *Iterator {
func (any *falseAny) GetInterface() interface{} { func (any *falseAny) GetInterface() interface{} {
return false return false
} }
func (any *falseAny) ValueType() ValueType {
return Bool
}

View File

@ -22,6 +22,10 @@ func (any *floatLazyAny) Parse() *Iterator {
return iter return iter
} }
func (any *floatLazyAny) ValueType() ValueType {
return Number
}
func (any *floatLazyAny) fillCache() { func (any *floatLazyAny) fillCache() {
if any.err != nil { if any.err != nil {
return return

View File

@ -14,6 +14,10 @@ type intLazyAny struct {
cache int64 cache int64
} }
func (any *intLazyAny) ValueType() ValueType {
return Number
}
func (any *intLazyAny) Parse() *Iterator { func (any *intLazyAny) Parse() *Iterator {
iter := any.iter iter := any.iter
if iter == nil { if iter == nil {
@ -91,6 +95,10 @@ func (any *intAny) LastError() error {
return any.err return any.err
} }
func (any *intAny) ValueType() ValueType {
return Number
}
func (any *intAny) ToBool() bool { func (any *intAny) ToBool() bool {
return any.ToInt64() != 0 return any.ToInt64() != 0
} }

View File

@ -1,11 +1,18 @@
package jsoniter package jsoniter
import "fmt"
type invalidAny struct { type invalidAny struct {
baseAny baseAny
err error
} }
func (any *invalidAny) LastError() error { func (any *invalidAny) LastError() error {
return nil return any.err
}
func (any *invalidAny) ValueType() ValueType {
return Invalid
} }
func (any *invalidAny) ToBool() bool { func (any *invalidAny) ToBool() bool {
@ -40,7 +47,11 @@ func (any *invalidAny) WriteTo(stream *Stream) {
} }
func (any *invalidAny) Get(path ...interface{}) Any { func (any *invalidAny) Get(path ...interface{}) Any {
return any if any.err == nil {
return &invalidAny{baseAny{}, fmt.Errorf("get %v from invalid", path)}
} else {
return &invalidAny{baseAny{}, fmt.Errorf("%v, get %v from invalid", any.err, path)}
}
} }
func (any *invalidAny) Parse() *Iterator { func (any *invalidAny) Parse() *Iterator {

View File

@ -8,6 +8,10 @@ func (any *nilAny) LastError() error {
return nil return nil
} }
func (any *nilAny) ValueType() ValueType {
return Nil
}
func (any *nilAny) ToBool() bool { func (any *nilAny) ToBool() bool {
return false return false
} }

View File

@ -2,6 +2,7 @@ package jsoniter
import ( import (
"unsafe" "unsafe"
"fmt"
) )
type objectLazyAny struct { type objectLazyAny struct {
@ -13,6 +14,10 @@ type objectLazyAny struct {
remaining []byte remaining []byte
} }
func (any *objectLazyAny) ValueType() ValueType {
return Object
}
func (any *objectLazyAny) Parse() *Iterator { func (any *objectLazyAny) Parse() *Iterator {
iter := any.iter iter := any.iter
if iter == nil { if iter == nil {
@ -178,12 +183,20 @@ func (any *objectLazyAny) Get(path ...interface{}) Any {
if len(path) == 0 { if len(path) == 0 {
return any return any
} }
if len(path) == 1 { var element Any
key := path[0].(string) key, ok := path[0].(string)
return any.fillCacheUntil(key) if ok {
element = any.fillCacheUntil(key)
if element == nil {
element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", key, any.cache)}
}
} else { } else {
key := path[0].(string) element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", key, any.cache)}
return any.fillCacheUntil(key).Get(path[1:]...) }
if len(path) == 1 {
return element
} else {
return element.Get(path[1:]...)
} }
} }

View File

@ -12,6 +12,10 @@ type stringLazyAny struct{
cache string cache string
} }
func (any *stringLazyAny) ValueType() ValueType {
return String
}
func (any *stringLazyAny) Parse() *Iterator { func (any *stringLazyAny) Parse() *Iterator {
iter := any.iter iter := any.iter
if iter == nil { if iter == nil {

View File

@ -90,6 +90,16 @@ func Test_array_lazy_any_get(t *testing.T) {
should.Equal("[1,[2,3],4]", any.ToString()) should.Equal("[1,[2,3],4]", any.ToString())
} }
func Test_array_lazy_any_get_invalid(t *testing.T) {
should := require.New(t)
any, err := UnmarshalAnyFromString("[]")
should.Nil(err)
should.Equal(Invalid, any.Get(1,1).ValueType())
should.NotNil(any.Get(1,1).LastError())
should.Equal(Invalid, any.Get("1").ValueType())
should.NotNil(any.Get("1").LastError())
}
func Test_array_lazy_any_set(t *testing.T) { func Test_array_lazy_any_set(t *testing.T) {
should := require.New(t) should := require.New(t)
any, err := UnmarshalAnyFromString("[1,[2,3],4]") any, err := UnmarshalAnyFromString("[1,[2,3],4]")

View File

@ -110,6 +110,13 @@ func Test_read_int64_as_any(t *testing.T) {
should.True(any.ToBool()) should.True(any.ToBool())
} }
func Test_int_lazy_any_get(t *testing.T) {
should := require.New(t)
any, err := UnmarshalAnyFromString("1234")
should.Nil(err)
should.Equal(Invalid, any.Get(1, "2").ValueType())
}
func Test_wrap_int(t *testing.T) { func Test_wrap_int(t *testing.T) {
should := require.New(t) should := require.New(t)
str, err := MarshalToString(WrapInt64(100)) str, err := MarshalToString(WrapInt64(100))

View File

@ -147,6 +147,14 @@ func Test_object_lazy_any_get(t *testing.T) {
should.Equal("d", any.Get("a", "b", "c").ToString()) should.Equal("d", any.Get("a", "b", "c").ToString())
} }
func Test_object_lazy_any_get_invalid(t *testing.T) {
should := require.New(t)
any, err := UnmarshalAnyFromString(`{}`)
should.Nil(err)
should.Equal(Invalid, any.Get("a", "b", "c").ValueType())
should.Equal(Invalid, any.Get(1).ValueType())
}
func Test_object_lazy_any_set(t *testing.T) { func Test_object_lazy_any_set(t *testing.T) {
should := require.New(t) should := require.New(t)
any, err := UnmarshalAnyFromString(`{"a":{"b":{"c":"d"}}}`) any, err := UnmarshalAnyFromString(`{"a":{"b":{"c":"d"}}}`)