1
0
mirror of https://github.com/json-iterator/go.git synced 2025-01-20 18:48:32 +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
import "fmt"
type Any interface {
LastError() error
ValueType() ValueType
ToBool() bool
ToInt() int
ToInt32() int32
@ -26,7 +29,7 @@ type Any interface {
type baseAny struct{}
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 {

View File

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

View File

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

View File

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

View File

@ -1,11 +1,18 @@
package jsoniter
import "fmt"
type invalidAny struct {
baseAny
err error
}
func (any *invalidAny) LastError() error {
return nil
return any.err
}
func (any *invalidAny) ValueType() ValueType {
return Invalid
}
func (any *invalidAny) ToBool() bool {
@ -40,7 +47,11 @@ func (any *invalidAny) WriteTo(stream *Stream) {
}
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 {

View File

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

View File

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

View File

@ -12,6 +12,10 @@ type stringLazyAny struct{
cache string
}
func (any *stringLazyAny) ValueType() ValueType {
return String
}
func (any *stringLazyAny) Parse() *Iterator {
iter := any.iter
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())
}
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) {
should := require.New(t)
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())
}
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) {
should := require.New(t)
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())
}
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) {
should := require.New(t)
any, err := UnmarshalAnyFromString(`{"a":{"b":{"c":"d"}}}`)