mirror of
https://github.com/json-iterator/go.git
synced 2025-06-06 22:36:25 +02:00
#61 removed internal buffer from lazy array and object; jsoniter.Get replaced jsoniter.UnmarshalAny
This commit is contained in:
parent
1ec246d16b
commit
985e263300
@ -24,11 +24,6 @@ func Unmarshal(data []byte, v interface{}) error {
|
|||||||
return ConfigDefault.Unmarshal(data, v)
|
return ConfigDefault.Unmarshal(data, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalAny adapts to
|
|
||||||
func UnmarshalAny(data []byte) (Any, error) {
|
|
||||||
return ConfigDefault.UnmarshalAny(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func lastNotSpacePos(data []byte) int {
|
func lastNotSpacePos(data []byte) int {
|
||||||
for i := len(data) - 1; i >= 0; i-- {
|
for i := len(data) - 1; i >= 0; i-- {
|
||||||
if data[i] != ' ' && data[i] != '\t' && data[i] != '\r' && data[i] != '\n' {
|
if data[i] != ' ' && data[i] != '\t' && data[i] != '\r' && data[i] != '\n' {
|
||||||
@ -42,10 +37,11 @@ func UnmarshalFromString(str string, v interface{}) error {
|
|||||||
return ConfigDefault.UnmarshalFromString(str, v)
|
return ConfigDefault.UnmarshalFromString(str, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UnmarshalAnyFromString(str string) (Any, error) {
|
func Get(data []byte, path ...interface{}) Any {
|
||||||
return ConfigDefault.UnmarshalAnyFromString(str)
|
return ConfigDefault.Get(data, path...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Marshal adapts to json/encoding Marshal API
|
// Marshal adapts to json/encoding Marshal API
|
||||||
//
|
//
|
||||||
// Marshal returns the JSON encoding of v, adapts to json/encoding Marshal API
|
// Marshal returns the JSON encoding of v, adapts to json/encoding Marshal API
|
||||||
|
@ -3,6 +3,7 @@ package jsoniter
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Any interface {
|
type Any interface {
|
||||||
@ -21,12 +22,8 @@ type Any interface {
|
|||||||
Get(path ...interface{}) Any
|
Get(path ...interface{}) Any
|
||||||
Size() int
|
Size() int
|
||||||
Keys() []string
|
Keys() []string
|
||||||
IterateObject() (func() (string, Any, bool), bool)
|
|
||||||
IterateArray() (func() (Any, bool), bool)
|
|
||||||
GetArray() []Any
|
GetArray() []Any
|
||||||
SetArray(newList []Any) bool
|
|
||||||
GetObject() map[string]Any
|
GetObject() map[string]Any
|
||||||
SetObject(map[string]Any) bool
|
|
||||||
GetInterface() interface{}
|
GetInterface() interface{}
|
||||||
WriteTo(stream *Stream)
|
WriteTo(stream *Stream)
|
||||||
}
|
}
|
||||||
@ -45,30 +42,14 @@ func (any *baseAny) Keys() []string {
|
|||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *baseAny) IterateObject() (func() (string, Any, bool), bool) {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (any *baseAny) IterateArray() (func() (Any, bool), bool) {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (any *baseAny) GetArray() []Any {
|
func (any *baseAny) GetArray() []Any {
|
||||||
return []Any{}
|
return []Any{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *baseAny) SetArray(newList []Any) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (any *baseAny) GetObject() map[string]Any {
|
func (any *baseAny) GetObject() map[string]Any {
|
||||||
return map[string]Any{}
|
return map[string]Any{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *baseAny) SetObject(map[string]Any) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func WrapInt32(val int32) Any {
|
func WrapInt32(val int32) Any {
|
||||||
return &int32Any{baseAny{}, val}
|
return &int32Any{baseAny{}, val}
|
||||||
}
|
}
|
||||||
@ -153,7 +134,8 @@ func (iter *Iterator) readAny() Any {
|
|||||||
c := iter.nextToken()
|
c := iter.nextToken()
|
||||||
switch c {
|
switch c {
|
||||||
case '"':
|
case '"':
|
||||||
return iter.readStringAny()
|
iter.unreadByte()
|
||||||
|
return &stringAny{baseAny{}, nil, iter.ReadString()}
|
||||||
case 'n':
|
case 'n':
|
||||||
iter.skipFixedBytes(3) // null
|
iter.skipFixedBytes(3) // null
|
||||||
return &nilAny{}
|
return &nilAny{}
|
||||||
@ -200,12 +182,59 @@ func (iter *Iterator) readObjectAny() Any {
|
|||||||
iter.startCapture(iter.head - 1)
|
iter.startCapture(iter.head - 1)
|
||||||
iter.skipObject()
|
iter.skipObject()
|
||||||
lazyBuf := iter.stopCapture()
|
lazyBuf := iter.stopCapture()
|
||||||
return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
|
return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) readArrayAny() Any {
|
func (iter *Iterator) readArrayAny() Any {
|
||||||
iter.startCapture(iter.head - 1)
|
iter.startCapture(iter.head - 1)
|
||||||
iter.skipArray()
|
iter.skipArray()
|
||||||
lazyBuf := iter.stopCapture()
|
lazyBuf := iter.stopCapture()
|
||||||
return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
|
return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
func locateObjectField(iter *Iterator, target string) []byte {
|
||||||
|
var found []byte
|
||||||
|
iter.ReadObjectCB(func(iter *Iterator, field string) bool {
|
||||||
|
if field == target {
|
||||||
|
found = iter.SkipAndReturnBytes()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
iter.Skip()
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
func locateArrayElement(iter *Iterator, target int) []byte {
|
||||||
|
var found []byte
|
||||||
|
n := 0
|
||||||
|
iter.ReadArrayCB(func(iter *Iterator) bool {
|
||||||
|
if n == target {
|
||||||
|
found = iter.SkipAndReturnBytes()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
iter.Skip()
|
||||||
|
n++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
func locatePath(iter *Iterator, path []interface{}) Any {
|
||||||
|
for i, pathKeyObj := range path {
|
||||||
|
switch pathKey := pathKeyObj.(type) {
|
||||||
|
case string:
|
||||||
|
valueBytes := locateObjectField(iter, pathKey)
|
||||||
|
iter.ResetBytes(valueBytes)
|
||||||
|
case int:
|
||||||
|
valueBytes := locateArrayElement(iter, pathKey)
|
||||||
|
iter.ResetBytes(valueBytes)
|
||||||
|
default:
|
||||||
|
return newInvalidAny(path[i:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
|
return &invalidAny{baseAny{}, iter.Error}
|
||||||
|
}
|
||||||
|
return iter.readAny()
|
||||||
}
|
}
|
@ -11,317 +11,157 @@ type arrayLazyAny struct {
|
|||||||
cfg *frozenConfig
|
cfg *frozenConfig
|
||||||
buf []byte
|
buf []byte
|
||||||
err error
|
err error
|
||||||
cache []Any
|
|
||||||
remaining []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) ValueType() ValueType {
|
func (any *arrayLazyAny) ValueType() ValueType {
|
||||||
return Array
|
return Array
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) fillCacheUntil(target int) Any {
|
|
||||||
if any.remaining == nil {
|
|
||||||
if target >= len(any.cache) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return any.cache[target]
|
|
||||||
}
|
|
||||||
if any.cache == nil {
|
|
||||||
any.cache = make([]Any, 0, 8)
|
|
||||||
}
|
|
||||||
i := len(any.cache)
|
|
||||||
if target < i {
|
|
||||||
return any.cache[target]
|
|
||||||
}
|
|
||||||
iter := any.cfg.BorrowIterator(any.remaining)
|
|
||||||
defer any.cfg.ReturnIterator(iter)
|
|
||||||
if len(any.remaining) == len(any.buf) {
|
|
||||||
iter.head++
|
|
||||||
c := iter.nextToken()
|
|
||||||
if c != ']' {
|
|
||||||
iter.unreadByte()
|
|
||||||
element := iter.readAny()
|
|
||||||
any.cache = append(any.cache, element)
|
|
||||||
if target == 0 {
|
|
||||||
any.remaining = iter.buf[iter.head:]
|
|
||||||
any.err = iter.Error
|
|
||||||
return element
|
|
||||||
}
|
|
||||||
i = 1
|
|
||||||
} else {
|
|
||||||
any.remaining = nil
|
|
||||||
any.err = iter.Error
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for iter.nextToken() == ',' {
|
|
||||||
element := iter.readAny()
|
|
||||||
any.cache = append(any.cache, element)
|
|
||||||
if i == target {
|
|
||||||
any.remaining = iter.buf[iter.head:]
|
|
||||||
any.err = iter.Error
|
|
||||||
return element
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
any.remaining = nil
|
|
||||||
any.err = iter.Error
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (any *arrayLazyAny) fillCache() {
|
|
||||||
if any.remaining == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if any.cache == nil {
|
|
||||||
any.cache = make([]Any, 0, 8)
|
|
||||||
}
|
|
||||||
iter := any.cfg.BorrowIterator(any.remaining)
|
|
||||||
defer any.cfg.ReturnIterator(iter)
|
|
||||||
if len(any.remaining) == len(any.buf) {
|
|
||||||
iter.head++
|
|
||||||
c := iter.nextToken()
|
|
||||||
if c != ']' {
|
|
||||||
iter.unreadByte()
|
|
||||||
any.cache = append(any.cache, iter.readAny())
|
|
||||||
} else {
|
|
||||||
any.remaining = nil
|
|
||||||
any.err = iter.Error
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for iter.nextToken() == ',' {
|
|
||||||
any.cache = append(any.cache, iter.readAny())
|
|
||||||
}
|
|
||||||
any.remaining = nil
|
|
||||||
any.err = iter.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (any *arrayLazyAny) LastError() error {
|
func (any *arrayLazyAny) LastError() error {
|
||||||
return any.err
|
return any.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) ToBool() bool {
|
func (any *arrayLazyAny) ToBool() bool {
|
||||||
if any.cache == nil {
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
any.IterateArray() // trigger first element read
|
defer any.cfg.ReturnIterator(iter)
|
||||||
}
|
return iter.ReadArray()
|
||||||
return len(any.cache) != 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) ToInt() int {
|
func (any *arrayLazyAny) ToInt() int {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateArray() // trigger first element read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) ToInt32() int32 {
|
func (any *arrayLazyAny) ToInt32() int32 {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateArray() // trigger first element read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) ToInt64() int64 {
|
func (any *arrayLazyAny) ToInt64() int64 {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateArray() // trigger first element read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) ToUint() uint {
|
func (any *arrayLazyAny) ToUint() uint {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateArray() // trigger first element read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) ToUint32() uint32 {
|
func (any *arrayLazyAny) ToUint32() uint32 {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateArray() // trigger first element read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) ToUint64() uint64 {
|
func (any *arrayLazyAny) ToUint64() uint64 {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateArray() // trigger first element read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) ToFloat32() float32 {
|
func (any *arrayLazyAny) ToFloat32() float32 {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateArray() // trigger first element read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) ToFloat64() float64 {
|
func (any *arrayLazyAny) ToFloat64() float64 {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateArray() // trigger first element read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) ToString() string {
|
func (any *arrayLazyAny) ToString() string {
|
||||||
if len(any.remaining) == len(any.buf) {
|
|
||||||
// nothing has been parsed yet
|
|
||||||
return *(*string)(unsafe.Pointer(&any.buf))
|
return *(*string)(unsafe.Pointer(&any.buf))
|
||||||
} else {
|
|
||||||
any.fillCache()
|
|
||||||
str, err := any.cfg.MarshalToString(any.cache)
|
|
||||||
any.err = err
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) Get(path ...interface{}) Any {
|
func (any *arrayLazyAny) Get(path ...interface{}) Any {
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
return any
|
return any
|
||||||
}
|
}
|
||||||
var element Any
|
|
||||||
switch firstPath := path[0].(type) {
|
switch firstPath := path[0].(type) {
|
||||||
case int:
|
case int:
|
||||||
element = any.fillCacheUntil(firstPath)
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
if element == nil {
|
defer any.cfg.ReturnIterator(iter)
|
||||||
element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)}
|
valueBytes := locateArrayElement(iter, firstPath)
|
||||||
|
if valueBytes == nil {
|
||||||
|
return newInvalidAny(path)
|
||||||
|
} else {
|
||||||
|
iter.ResetBytes(valueBytes)
|
||||||
|
return locatePath(iter, path[1:])
|
||||||
}
|
}
|
||||||
case int32:
|
case int32:
|
||||||
if '*' == firstPath {
|
if '*' == firstPath {
|
||||||
any.fillCache()
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
arr := make([]Any, 0, len(any.cache))
|
defer any.cfg.ReturnIterator(iter)
|
||||||
for _, element := range any.cache {
|
arr := make([]Any, 0)
|
||||||
found := element.Get(path[1:]...)
|
iter.ReadArrayCB(func(iter *Iterator) bool {
|
||||||
|
found := iter.readAny().Get(path[1:]...)
|
||||||
if found.ValueType() != Invalid {
|
if found.ValueType() != Invalid {
|
||||||
arr = append(arr, found)
|
arr = append(arr, found)
|
||||||
}
|
}
|
||||||
}
|
return true
|
||||||
|
})
|
||||||
return wrapArray(arr)
|
return wrapArray(arr)
|
||||||
} else {
|
} else {
|
||||||
element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", path[0], any.cache)}
|
return newInvalidAny(path)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", path[0], any.cache)}
|
return newInvalidAny(path)
|
||||||
}
|
|
||||||
if len(path) == 1 {
|
|
||||||
return element
|
|
||||||
} else {
|
|
||||||
return element.Get(path[1:]...)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) Size() int {
|
func (any *arrayLazyAny) Size() int {
|
||||||
any.fillCache()
|
size := 0
|
||||||
return len(any.cache)
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
}
|
|
||||||
|
|
||||||
func (any *arrayLazyAny) IterateArray() (func() (Any, bool), bool) {
|
|
||||||
if any.cache == nil {
|
|
||||||
any.cache = make([]Any, 0, 8)
|
|
||||||
}
|
|
||||||
remaining := any.remaining
|
|
||||||
if len(remaining) == len(any.buf) {
|
|
||||||
iter := any.cfg.BorrowIterator(any.remaining)
|
|
||||||
defer any.cfg.ReturnIterator(iter)
|
defer any.cfg.ReturnIterator(iter)
|
||||||
iter.head++
|
iter.ReadArrayCB(func(iter *Iterator) bool {
|
||||||
c := iter.nextToken()
|
size++
|
||||||
if c != ']' {
|
iter.Skip()
|
||||||
iter.unreadByte()
|
return true
|
||||||
v := iter.readAny()
|
})
|
||||||
any.cache = append(any.cache, v)
|
return size
|
||||||
remaining = iter.buf[iter.head:]
|
|
||||||
any.remaining = remaining
|
|
||||||
} else {
|
|
||||||
remaining = nil
|
|
||||||
any.remaining = nil
|
|
||||||
any.err = iter.Error
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
arr := any.cache
|
|
||||||
nextValue := arr[0]
|
|
||||||
i := 1
|
|
||||||
return func() (Any, bool) {
|
|
||||||
value := nextValue
|
|
||||||
if i < len(arr) {
|
|
||||||
// read from cache
|
|
||||||
nextValue = arr[i]
|
|
||||||
i++
|
|
||||||
return value, true
|
|
||||||
} else {
|
|
||||||
// read from buffer
|
|
||||||
iter := any.cfg.BorrowIterator(any.remaining)
|
|
||||||
defer any.cfg.ReturnIterator(iter)
|
|
||||||
c := iter.nextToken()
|
|
||||||
if c == ',' {
|
|
||||||
nextValue = iter.readAny()
|
|
||||||
any.cache = append(any.cache, nextValue)
|
|
||||||
remaining = iter.buf[iter.head:]
|
|
||||||
any.remaining = remaining
|
|
||||||
any.err = iter.Error
|
|
||||||
return value, true
|
|
||||||
} else {
|
|
||||||
remaining = nil
|
|
||||||
any.remaining = nil
|
|
||||||
any.err = iter.Error
|
|
||||||
return value, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) GetArray() []Any {
|
func (any *arrayLazyAny) GetArray() []Any {
|
||||||
any.fillCache()
|
elements := make([]Any, 0)
|
||||||
return any.cache
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
}
|
defer any.cfg.ReturnIterator(iter)
|
||||||
|
iter.ReadArrayCB(func(iter *Iterator) bool {
|
||||||
func (any *arrayLazyAny) SetArray(newList []Any) bool {
|
elements = append(elements, iter.ReadAny())
|
||||||
any.fillCache()
|
|
||||||
any.cache = newList
|
|
||||||
return true
|
return true
|
||||||
|
})
|
||||||
|
return elements
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) WriteTo(stream *Stream) {
|
func (any *arrayLazyAny) WriteTo(stream *Stream) {
|
||||||
if len(any.remaining) == len(any.buf) {
|
|
||||||
// nothing has been parsed yet
|
|
||||||
stream.Write(any.buf)
|
stream.Write(any.buf)
|
||||||
} else {
|
|
||||||
any.fillCache()
|
|
||||||
stream.WriteVal(any.cache)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayLazyAny) GetInterface() interface{} {
|
func (any *arrayLazyAny) GetInterface() interface{} {
|
||||||
any.fillCache()
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
return any.cache
|
defer any.cfg.ReturnIterator(iter)
|
||||||
|
return iter.Read()
|
||||||
}
|
}
|
||||||
|
|
||||||
type arrayAny struct {
|
type arrayAny struct {
|
||||||
@ -506,12 +346,6 @@ func (any *arrayAny) GetArray() []Any {
|
|||||||
return any.cache
|
return any.cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *arrayAny) SetArray(newList []Any) bool {
|
|
||||||
any.fillCache()
|
|
||||||
any.cache = newList
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (any *arrayAny) WriteTo(stream *Stream) {
|
func (any *arrayAny) WriteTo(stream *Stream) {
|
||||||
if len(any.cache) == 0 {
|
if len(any.cache) == 0 {
|
||||||
// nothing has been parsed yet
|
// nothing has been parsed yet
|
||||||
|
@ -7,6 +7,10 @@ type invalidAny struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newInvalidAny(path []interface{}) *invalidAny {
|
||||||
|
return &invalidAny{baseAny{}, fmt.Errorf("%v not found", path)}
|
||||||
|
}
|
||||||
|
|
||||||
func (any *invalidAny) LastError() error {
|
func (any *invalidAny) LastError() error {
|
||||||
return any.err
|
return any.err
|
||||||
}
|
}
|
||||||
|
@ -11,340 +11,169 @@ type objectLazyAny struct {
|
|||||||
cfg *frozenConfig
|
cfg *frozenConfig
|
||||||
buf []byte
|
buf []byte
|
||||||
err error
|
err error
|
||||||
cache map[string]Any
|
|
||||||
remaining []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) ValueType() ValueType {
|
func (any *objectLazyAny) ValueType() ValueType {
|
||||||
return Object
|
return Object
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) fillCacheUntil(target string) Any {
|
|
||||||
if any.remaining == nil {
|
|
||||||
return any.cache[target]
|
|
||||||
}
|
|
||||||
if any.cache == nil {
|
|
||||||
any.cache = map[string]Any{}
|
|
||||||
}
|
|
||||||
val := any.cache[target]
|
|
||||||
if val != nil {
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
iter := any.cfg.BorrowIterator(any.remaining)
|
|
||||||
defer any.cfg.ReturnIterator(iter)
|
|
||||||
if len(any.remaining) == len(any.buf) {
|
|
||||||
iter.head++
|
|
||||||
c := iter.nextToken()
|
|
||||||
if c != '}' {
|
|
||||||
iter.unreadByte()
|
|
||||||
k := string(iter.readObjectFieldAsBytes())
|
|
||||||
v := iter.readAny()
|
|
||||||
any.cache[k] = v
|
|
||||||
if target == k {
|
|
||||||
any.remaining = iter.buf[iter.head:]
|
|
||||||
any.err = iter.Error
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
any.remaining = nil
|
|
||||||
any.err = iter.Error
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for iter.nextToken() == ',' {
|
|
||||||
k := string(iter.readObjectFieldAsBytes())
|
|
||||||
v := iter.readAny()
|
|
||||||
any.cache[k] = v
|
|
||||||
if target == k {
|
|
||||||
any.remaining = iter.buf[iter.head:]
|
|
||||||
any.err = iter.Error
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
any.remaining = nil
|
|
||||||
any.err = iter.Error
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (any *objectLazyAny) fillCache() {
|
|
||||||
if any.remaining == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if any.cache == nil {
|
|
||||||
any.cache = map[string]Any{}
|
|
||||||
}
|
|
||||||
iter := any.cfg.BorrowIterator(any.remaining)
|
|
||||||
defer any.cfg.ReturnIterator(iter)
|
|
||||||
if len(any.remaining) == len(any.buf) {
|
|
||||||
iter.head++
|
|
||||||
c := iter.nextToken()
|
|
||||||
if c != '}' {
|
|
||||||
iter.unreadByte()
|
|
||||||
k := string(iter.readObjectFieldAsBytes())
|
|
||||||
v := iter.readAny()
|
|
||||||
any.cache[k] = v
|
|
||||||
} else {
|
|
||||||
any.remaining = nil
|
|
||||||
any.err = iter.Error
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for iter.nextToken() == ',' {
|
|
||||||
k := string(iter.readObjectFieldAsBytes())
|
|
||||||
v := iter.readAny()
|
|
||||||
any.cache[k] = v
|
|
||||||
}
|
|
||||||
any.remaining = nil
|
|
||||||
any.err = iter.Error
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (any *objectLazyAny) LastError() error {
|
func (any *objectLazyAny) LastError() error {
|
||||||
return any.err
|
return any.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) ToBool() bool {
|
func (any *objectLazyAny) ToBool() bool {
|
||||||
if any.cache == nil {
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
any.IterateObject() // trigger first value read
|
defer any.cfg.ReturnIterator(iter)
|
||||||
}
|
return iter.ReadObject() != ""
|
||||||
return len(any.cache) != 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) ToInt() int {
|
func (any *objectLazyAny) ToInt() int {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateObject() // trigger first value read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) ToInt32() int32 {
|
func (any *objectLazyAny) ToInt32() int32 {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateObject() // trigger first value read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) ToInt64() int64 {
|
func (any *objectLazyAny) ToInt64() int64 {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateObject() // trigger first value read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) ToUint() uint {
|
func (any *objectLazyAny) ToUint() uint {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateObject() // trigger first value read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) ToUint32() uint32 {
|
func (any *objectLazyAny) ToUint32() uint32 {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateObject() // trigger first value read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) ToUint64() uint64 {
|
func (any *objectLazyAny) ToUint64() uint64 {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateObject() // trigger first value read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) ToFloat32() float32 {
|
func (any *objectLazyAny) ToFloat32() float32 {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateObject() // trigger first value read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) ToFloat64() float64 {
|
func (any *objectLazyAny) ToFloat64() float64 {
|
||||||
if any.cache == nil {
|
if any.ToBool() {
|
||||||
any.IterateObject() // trigger first value read
|
return 1
|
||||||
}
|
} else {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) ToString() string {
|
func (any *objectLazyAny) ToString() string {
|
||||||
if len(any.remaining) == len(any.buf) {
|
|
||||||
// nothing has been parsed yet
|
|
||||||
return *(*string)(unsafe.Pointer(&any.buf))
|
return *(*string)(unsafe.Pointer(&any.buf))
|
||||||
} else {
|
|
||||||
any.fillCache()
|
|
||||||
str, err := any.cfg.MarshalToString(any.cache)
|
|
||||||
any.err = err
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) Get(path ...interface{}) Any {
|
func (any *objectLazyAny) Get(path ...interface{}) Any {
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
return any
|
return any
|
||||||
}
|
}
|
||||||
var element Any
|
|
||||||
|
|
||||||
switch firstPath := path[0].(type) {
|
switch firstPath := path[0].(type) {
|
||||||
case string:
|
case string:
|
||||||
element = any.fillCacheUntil(firstPath)
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
if element == nil {
|
defer any.cfg.ReturnIterator(iter)
|
||||||
element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)}
|
valueBytes := locateObjectField(iter, firstPath)
|
||||||
|
if valueBytes == nil {
|
||||||
|
return newInvalidAny(path)
|
||||||
|
} else {
|
||||||
|
iter.ResetBytes(valueBytes)
|
||||||
|
return locatePath(iter, path[1:])
|
||||||
}
|
}
|
||||||
case int32:
|
case int32:
|
||||||
if '*' == firstPath {
|
if '*' == firstPath {
|
||||||
any.fillCache()
|
|
||||||
mappedAll := map[string]Any{}
|
mappedAll := map[string]Any{}
|
||||||
for key, value := range any.cache {
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
mapped := value.Get(path[1:]...)
|
defer any.cfg.ReturnIterator(iter)
|
||||||
|
iter.ReadObjectCB(func(iter *Iterator, field string) bool {
|
||||||
|
mapped := locatePath(iter, path[1:])
|
||||||
if mapped.ValueType() != Invalid {
|
if mapped.ValueType() != Invalid {
|
||||||
mappedAll[key] = mapped
|
mappedAll[field] = mapped
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
return wrapMap(mappedAll)
|
return wrapMap(mappedAll)
|
||||||
} else {
|
} else {
|
||||||
element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)}
|
return newInvalidAny(path)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)}
|
return newInvalidAny(path)
|
||||||
}
|
|
||||||
if len(path) == 1 {
|
|
||||||
return element
|
|
||||||
} else {
|
|
||||||
return element.Get(path[1:]...)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) Keys() []string {
|
func (any *objectLazyAny) Keys() []string {
|
||||||
any.fillCache()
|
keys := []string{}
|
||||||
keys := make([]string, 0, len(any.cache))
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
for key := range any.cache {
|
defer any.cfg.ReturnIterator(iter)
|
||||||
keys = append(keys, key)
|
iter.ReadObjectCB(func(iter *Iterator, field string) bool {
|
||||||
}
|
iter.Skip()
|
||||||
|
keys = append(keys, field)
|
||||||
|
return true
|
||||||
|
})
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) Size() int {
|
func (any *objectLazyAny) Size() int {
|
||||||
any.fillCache()
|
size := 0
|
||||||
return len(any.cache)
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
}
|
|
||||||
|
|
||||||
func (any *objectLazyAny) IterateObject() (func() (string, Any, bool), bool) {
|
|
||||||
if any.cache == nil {
|
|
||||||
any.cache = map[string]Any{}
|
|
||||||
}
|
|
||||||
remaining := any.remaining
|
|
||||||
if len(remaining) == len(any.buf) {
|
|
||||||
iter := any.cfg.BorrowIterator(any.remaining)
|
|
||||||
defer any.cfg.ReturnIterator(iter)
|
defer any.cfg.ReturnIterator(iter)
|
||||||
iter.head++
|
iter.ReadObjectCB(func(iter *Iterator, field string) bool {
|
||||||
c := iter.nextToken()
|
iter.Skip()
|
||||||
if c != '}' {
|
size ++
|
||||||
iter.unreadByte()
|
return true
|
||||||
k := string(iter.readObjectFieldAsBytes())
|
})
|
||||||
v := iter.readAny()
|
return size
|
||||||
any.cache[k] = v
|
|
||||||
remaining = iter.buf[iter.head:]
|
|
||||||
any.remaining = remaining
|
|
||||||
} else {
|
|
||||||
remaining = nil
|
|
||||||
any.remaining = nil
|
|
||||||
any.err = iter.Error
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
keys := make([]string, 0, len(any.cache))
|
|
||||||
values := make([]Any, 0, len(any.cache))
|
|
||||||
for key, value := range any.cache {
|
|
||||||
keys = append(keys, key)
|
|
||||||
values = append(values, value)
|
|
||||||
}
|
|
||||||
nextKey := keys[0]
|
|
||||||
nextValue := values[0]
|
|
||||||
i := 1
|
|
||||||
return func() (string, Any, bool) {
|
|
||||||
key := nextKey
|
|
||||||
value := nextValue
|
|
||||||
if i < len(keys) {
|
|
||||||
// read from cache
|
|
||||||
nextKey = keys[i]
|
|
||||||
nextValue = values[i]
|
|
||||||
i++
|
|
||||||
return key, value, true
|
|
||||||
} else {
|
|
||||||
// read from buffer
|
|
||||||
iter := any.cfg.BorrowIterator(any.remaining)
|
|
||||||
defer any.cfg.ReturnIterator(iter)
|
|
||||||
c := iter.nextToken()
|
|
||||||
if c == ',' {
|
|
||||||
nextKey = string(iter.readObjectFieldAsBytes())
|
|
||||||
nextValue = iter.readAny()
|
|
||||||
any.cache[nextKey] = nextValue
|
|
||||||
remaining = iter.buf[iter.head:]
|
|
||||||
any.remaining = remaining
|
|
||||||
any.err = iter.Error
|
|
||||||
return key, value, true
|
|
||||||
} else {
|
|
||||||
nextKey = ""
|
|
||||||
remaining = nil
|
|
||||||
any.remaining = nil
|
|
||||||
any.err = iter.Error
|
|
||||||
return key, value, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) GetObject() map[string]Any {
|
func (any *objectLazyAny) GetObject() map[string]Any {
|
||||||
any.fillCache()
|
asMap := map[string]Any{}
|
||||||
return any.cache
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
}
|
defer any.cfg.ReturnIterator(iter)
|
||||||
|
iter.ReadObjectCB(func(iter *Iterator, field string) bool {
|
||||||
func (any *objectLazyAny) SetObject(val map[string]Any) bool {
|
asMap[field] = iter.ReadAny()
|
||||||
any.fillCache()
|
|
||||||
any.cache = val
|
|
||||||
return true
|
return true
|
||||||
|
})
|
||||||
|
return asMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) WriteTo(stream *Stream) {
|
func (any *objectLazyAny) WriteTo(stream *Stream) {
|
||||||
if len(any.remaining) == len(any.buf) {
|
|
||||||
// nothing has been parsed yet
|
|
||||||
stream.Write(any.buf)
|
stream.Write(any.buf)
|
||||||
} else {
|
|
||||||
any.fillCache()
|
|
||||||
stream.WriteVal(any.cache)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectLazyAny) GetInterface() interface{} {
|
func (any *objectLazyAny) GetInterface() interface{} {
|
||||||
any.fillCache()
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
return any.cache
|
defer any.cfg.ReturnIterator(iter)
|
||||||
|
return iter.Read()
|
||||||
}
|
}
|
||||||
|
|
||||||
type objectAny struct {
|
type objectAny struct {
|
||||||
@ -537,57 +366,11 @@ func (any *objectAny) Size() int {
|
|||||||
return len(any.cache)
|
return len(any.cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectAny) IterateObject() (func() (string, Any, bool), bool) {
|
|
||||||
if any.cache == nil {
|
|
||||||
any.cache = map[string]Any{}
|
|
||||||
}
|
|
||||||
if any.val.NumField() == 0 {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
cacheKeys := make([]string, len(any.cache))
|
|
||||||
i := 0
|
|
||||||
for key := range any.cache {
|
|
||||||
cacheKeys[i] = key
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
i = 0
|
|
||||||
return func() (string, Any, bool) {
|
|
||||||
if i == any.val.NumField() {
|
|
||||||
return "", nil, false
|
|
||||||
}
|
|
||||||
var fieldName string
|
|
||||||
var fieldValueAsAny Any
|
|
||||||
if i == len(cacheKeys) {
|
|
||||||
fieldName = any.val.Type().Field(i).Name
|
|
||||||
cacheKeys = append(cacheKeys, fieldName)
|
|
||||||
fieldValue := any.val.Field(i)
|
|
||||||
if fieldValue.CanInterface() {
|
|
||||||
fieldValueAsAny = Wrap(fieldValue.Interface())
|
|
||||||
any.cache[fieldName] = fieldValueAsAny
|
|
||||||
} else {
|
|
||||||
fieldValueAsAny = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", fieldName, any.cache)}
|
|
||||||
any.cache[fieldName] = fieldValueAsAny
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fieldName = cacheKeys[i]
|
|
||||||
fieldValueAsAny = any.cache[fieldName]
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
return fieldName, fieldValueAsAny, i != any.val.NumField()
|
|
||||||
}, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (any *objectAny) GetObject() map[string]Any {
|
func (any *objectAny) GetObject() map[string]Any {
|
||||||
any.fillCache()
|
any.fillCache()
|
||||||
return any.cache
|
return any.cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectAny) SetObject(val map[string]Any) bool {
|
|
||||||
any.fillCache()
|
|
||||||
any.cache = val
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (any *objectAny) WriteTo(stream *Stream) {
|
func (any *objectAny) WriteTo(stream *Stream) {
|
||||||
if len(any.cache) == 0 {
|
if len(any.cache) == 0 {
|
||||||
// nothing has been parsed yet
|
// nothing has been parsed yet
|
||||||
@ -785,42 +568,11 @@ func (any *mapAny) Size() int {
|
|||||||
return len(any.cache)
|
return len(any.cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *mapAny) IterateObject() (func() (string, Any, bool), bool) {
|
|
||||||
any.fillCache()
|
|
||||||
if len(any.cache) == 0 {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
keys := make([]string, len(any.cache))
|
|
||||||
values := make([]Any, len(any.cache))
|
|
||||||
i := 0
|
|
||||||
for k, v := range any.cache {
|
|
||||||
keys[i] = k
|
|
||||||
values[i] = v
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
i = 0
|
|
||||||
return func() (string, Any, bool) {
|
|
||||||
if i == len(keys) {
|
|
||||||
return "", nil, false
|
|
||||||
}
|
|
||||||
k := keys[i]
|
|
||||||
v := values[i]
|
|
||||||
i++
|
|
||||||
return k, v, i != len(keys)
|
|
||||||
}, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (any *mapAny) GetObject() map[string]Any {
|
func (any *mapAny) GetObject() map[string]Any {
|
||||||
any.fillCache()
|
any.fillCache()
|
||||||
return any.cache
|
return any.cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *mapAny) SetObject(val map[string]Any) bool {
|
|
||||||
any.fillCache()
|
|
||||||
any.cache = val
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (any *mapAny) WriteTo(stream *Stream) {
|
func (any *mapAny) WriteTo(stream *Stream) {
|
||||||
if len(any.cache) == 0 {
|
if len(any.cache) == 0 {
|
||||||
// nothing has been parsed yet
|
// nothing has been parsed yet
|
||||||
|
@ -122,8 +122,9 @@ func (any *stringLazyAny) ToFloat64() float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (any *stringLazyAny) ToString() string {
|
func (any *stringLazyAny) ToString() string {
|
||||||
any.fillCache()
|
var val string
|
||||||
return any.cache
|
any.err = any.cfg.Unmarshal(any.buf, &val)
|
||||||
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *stringLazyAny) WriteTo(stream *Stream) {
|
func (any *stringLazyAny) WriteTo(stream *Stream) {
|
||||||
|
@ -206,39 +206,10 @@ func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
|
|||||||
return iter.Error
|
return iter.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *frozenConfig) UnmarshalAnyFromString(str string) (Any, error) {
|
func (cfg *frozenConfig) Get(data []byte, path ...interface{}) Any {
|
||||||
data := []byte(str)
|
|
||||||
data = data[:lastNotSpacePos(data)]
|
|
||||||
iter := cfg.BorrowIterator(data)
|
iter := cfg.BorrowIterator(data)
|
||||||
defer cfg.ReturnIterator(iter)
|
defer cfg.ReturnIterator(iter)
|
||||||
any := iter.ReadAny()
|
return locatePath(iter, path)
|
||||||
if iter.head == iter.tail {
|
|
||||||
iter.loadMore()
|
|
||||||
}
|
|
||||||
if iter.Error == io.EOF {
|
|
||||||
return any, nil
|
|
||||||
}
|
|
||||||
if iter.Error == nil {
|
|
||||||
iter.reportError("UnmarshalAnyFromString", "there are bytes left after unmarshal")
|
|
||||||
}
|
|
||||||
return nil, iter.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cfg *frozenConfig) UnmarshalAny(data []byte) (Any, error) {
|
|
||||||
data = data[:lastNotSpacePos(data)]
|
|
||||||
iter := cfg.BorrowIterator(data)
|
|
||||||
defer cfg.ReturnIterator(iter)
|
|
||||||
any := iter.ReadAny()
|
|
||||||
if iter.head == iter.tail {
|
|
||||||
iter.loadMore()
|
|
||||||
}
|
|
||||||
if iter.Error == io.EOF {
|
|
||||||
return any, nil
|
|
||||||
}
|
|
||||||
if iter.Error == nil {
|
|
||||||
iter.reportError("UnmarshalAny", "there are bytes left after unmarshal")
|
|
||||||
}
|
|
||||||
return any, iter.Error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error {
|
func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error {
|
||||||
|
@ -124,7 +124,6 @@ func (iter *Iterator) Reset(reader io.Reader) *Iterator {
|
|||||||
// ResetBytes can reset an Iterator instance for another json byte slice
|
// ResetBytes can reset an Iterator instance for another json byte slice
|
||||||
func (iter *Iterator) ResetBytes(input []byte) *Iterator {
|
func (iter *Iterator) ResetBytes(input []byte) *Iterator {
|
||||||
iter.reader = nil
|
iter.reader = nil
|
||||||
iter.Error = nil
|
|
||||||
iter.buf = input
|
iter.buf = input
|
||||||
iter.head = 0
|
iter.head = 0
|
||||||
iter.tail = len(input)
|
iter.tail = len(input)
|
||||||
|
@ -15,6 +15,7 @@ func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *frozenConfig) ReturnStream(stream *Stream) {
|
func (cfg *frozenConfig) ReturnStream(stream *Stream) {
|
||||||
|
stream.Error = nil
|
||||||
select {
|
select {
|
||||||
case cfg.streamPool <- stream:
|
case cfg.streamPool <- stream:
|
||||||
return
|
return
|
||||||
@ -34,6 +35,7 @@ func (cfg *frozenConfig) BorrowIterator(data []byte) *Iterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *frozenConfig) ReturnIterator(iter *Iterator) {
|
func (cfg *frozenConfig) ReturnIterator(iter *Iterator) {
|
||||||
|
iter.Error = nil
|
||||||
select {
|
select {
|
||||||
case cfg.iteratorPool <- iter:
|
case cfg.iteratorPool <- iter:
|
||||||
return
|
return
|
||||||
|
@ -3,75 +3,62 @@ package jsoniter
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"github.com/json-iterator/go/require"
|
"github.com/json-iterator/go/require"
|
||||||
"io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_read_empty_array_as_any(t *testing.T) {
|
func Test_read_empty_array_as_any(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString("[]")
|
any := Get([]byte("[]"))
|
||||||
should.Nil(err)
|
should.Equal(Array, any.Get().ValueType())
|
||||||
|
should.Equal(Invalid, any.Get(0.3).ValueType())
|
||||||
should.Equal(0, any.Size())
|
should.Equal(0, any.Size())
|
||||||
|
should.Equal(Array, any.ValueType())
|
||||||
|
should.Nil(any.LastError())
|
||||||
|
should.Equal(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())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_read_one_element_array_as_any(t *testing.T) {
|
func Test_read_one_element_array_as_any(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString("[1]")
|
any := Get([]byte("[1]"))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal(1, any.Size())
|
should.Equal(1, any.Size())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_read_two_element_array_as_any(t *testing.T) {
|
func Test_read_two_element_array_as_any(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString("[1,2]")
|
any := Get([]byte("[1,2]"))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal(1, any.Get(0).ToInt())
|
should.Equal(1, any.Get(0).ToInt())
|
||||||
should.Equal(2, any.Size())
|
should.Equal(2, any.Size())
|
||||||
should.True(any.ToBool())
|
should.True(any.ToBool())
|
||||||
should.Equal(1, any.ToInt())
|
should.Equal(1, any.ToInt())
|
||||||
}
|
should.Equal(1, any.GetArray()[0].ToInt())
|
||||||
|
should.Equal([]interface{}{float64(1), float64(2)}, any.GetInterface())
|
||||||
func Test_read_array_with_any_iterator(t *testing.T) {
|
stream := NewStream(ConfigDefault, nil, 32)
|
||||||
should := require.New(t)
|
any.WriteTo(stream)
|
||||||
any, err := UnmarshalAnyFromString("[1,2]")
|
should.Equal("[1,2]", string(stream.Buffer()))
|
||||||
should.Nil(err)
|
|
||||||
var element Any
|
|
||||||
var elements []int
|
|
||||||
for next, hasNext := any.IterateArray(); hasNext; {
|
|
||||||
element, hasNext = next()
|
|
||||||
elements = append(elements, element.ToInt())
|
|
||||||
}
|
|
||||||
should.Equal([]int{1, 2}, elements)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_wrap_array(t *testing.T) {
|
func Test_wrap_array(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any := Wrap([]int{1, 2, 3})
|
any := Wrap([]int{1, 2, 3})
|
||||||
should.Equal("[1,2,3]", any.ToString())
|
should.Equal("[1,2,3]", any.ToString())
|
||||||
var element Any
|
|
||||||
var elements []int
|
|
||||||
for next, hasNext := any.IterateArray(); hasNext; {
|
|
||||||
element, hasNext = next()
|
|
||||||
elements = append(elements, element.ToInt())
|
|
||||||
}
|
|
||||||
should.Equal([]int{1, 2, 3}, elements)
|
|
||||||
any = Wrap([]int{1, 2, 3})
|
|
||||||
should.Equal(3, any.Size())
|
|
||||||
any = Wrap([]int{1, 2, 3})
|
|
||||||
should.Equal(2, any.Get(1).ToInt())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_array_lazy_any_get(t *testing.T) {
|
func Test_array_lazy_any_get(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString("[1,[2,3],4]")
|
any := Get([]byte("[1,[2,3],4]"))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal(3, any.Get(1, 1).ToInt())
|
should.Equal(3, any.Get(1, 1).ToInt())
|
||||||
should.Equal("[1,[2,3],4]", any.ToString())
|
should.Equal("[1,[2,3],4]", any.ToString())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_array_lazy_any_get_all(t *testing.T) {
|
func Test_array_lazy_any_get_all(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString("[[1],[2],[3,4]]")
|
any := Get([]byte("[[1],[2],[3,4]]"))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal("[1,2,3]", any.Get('*', 0).ToString())
|
should.Equal("[1,2,3]", any.Get('*', 0).ToString())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,27 +74,15 @@ func Test_array_wrapper_any_get_all(t *testing.T) {
|
|||||||
|
|
||||||
func Test_array_lazy_any_get_invalid(t *testing.T) {
|
func Test_array_lazy_any_get_invalid(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString("[]")
|
any := Get([]byte("[]"))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal(Invalid, any.Get(1, 1).ValueType())
|
should.Equal(Invalid, any.Get(1, 1).ValueType())
|
||||||
should.NotNil(any.Get(1, 1).LastError())
|
should.NotNil(any.Get(1, 1).LastError())
|
||||||
should.Equal(Invalid, any.Get("1").ValueType())
|
should.Equal(Invalid, any.Get("1").ValueType())
|
||||||
should.NotNil(any.Get("1").LastError())
|
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]")
|
|
||||||
should.Nil(err)
|
|
||||||
any.GetArray()[0] = WrapInt64(2)
|
|
||||||
str, err := MarshalToString(any)
|
|
||||||
should.Nil(err)
|
|
||||||
should.Equal("[2,[2,3],4]", str)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_invalid_array(t *testing.T) {
|
func Test_invalid_array(t *testing.T) {
|
||||||
_, err := UnmarshalAnyFromString("[")
|
should := require.New(t)
|
||||||
if err == nil || err == io.EOF {
|
any := Get([]byte("["), 0)
|
||||||
t.FailNow()
|
should.Equal(Invalid, any.ValueType())
|
||||||
}
|
|
||||||
}
|
}
|
@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
func Test_read_bool_as_any(t *testing.T) {
|
func Test_read_bool_as_any(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString("true")
|
any := Get([]byte("true"))
|
||||||
should.Nil(err)
|
|
||||||
should.True(any.ToBool())
|
should.True(any.ToBool())
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,7 @@ import (
|
|||||||
|
|
||||||
func Test_read_float_as_any(t *testing.T) {
|
func Test_read_float_as_any(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString("12.3")
|
any := Get([]byte("12.3"))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal(float64(12.3), any.ToFloat64())
|
should.Equal(float64(12.3), any.ToFloat64())
|
||||||
should.Equal("12.3", any.ToString())
|
should.Equal("12.3", any.ToString())
|
||||||
should.True(any.ToBool())
|
should.True(any.ToBool())
|
||||||
|
@ -8,8 +8,7 @@ import (
|
|||||||
|
|
||||||
func Test_read_int64_as_any(t *testing.T) {
|
func Test_read_int64_as_any(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString("1234")
|
any := Get([]byte("1234"))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal(1234, any.ToInt())
|
should.Equal(1234, any.ToInt())
|
||||||
should.Equal(io.EOF, any.LastError())
|
should.Equal(io.EOF, any.LastError())
|
||||||
should.Equal("1234", any.ToString())
|
should.Equal("1234", any.ToString())
|
||||||
@ -18,7 +17,6 @@ func Test_read_int64_as_any(t *testing.T) {
|
|||||||
|
|
||||||
func Test_int_lazy_any_get(t *testing.T) {
|
func Test_int_lazy_any_get(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString("1234")
|
any := Get([]byte("1234"))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal(Invalid, any.Get(1, "2").ValueType())
|
should.Equal(Invalid, any.Get(1, "2").ValueType())
|
||||||
}
|
}
|
||||||
|
@ -11,15 +11,4 @@ func Test_wrap_map(t *testing.T) {
|
|||||||
should.Equal("hello", any.Get("Field1").ToString())
|
should.Equal("hello", any.Get("Field1").ToString())
|
||||||
any = Wrap(map[string]string{"Field1": "hello"})
|
any = Wrap(map[string]string{"Field1": "hello"})
|
||||||
should.Equal(1, any.Size())
|
should.Equal(1, any.Size())
|
||||||
any = Wrap(map[string]string{"Field1": "hello"})
|
|
||||||
vals := map[string]string{}
|
|
||||||
var k string
|
|
||||||
var v Any
|
|
||||||
for next, hasNext := any.IterateObject(); hasNext; {
|
|
||||||
k, v, hasNext = next()
|
|
||||||
if v.ValueType() == String {
|
|
||||||
vals[k] = v.ToString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
should.Equal(map[string]string{"Field1": "hello"}, vals)
|
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,7 @@ import (
|
|||||||
|
|
||||||
func Test_read_null_as_any(t *testing.T) {
|
func Test_read_null_as_any(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString(`null`)
|
any := Get([]byte(`null`))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal(0, any.ToInt())
|
should.Equal(0, any.ToInt())
|
||||||
should.Equal(float64(0), any.ToFloat64())
|
should.Equal(float64(0), any.ToFloat64())
|
||||||
should.Equal("", any.ToString())
|
should.Equal("", any.ToString())
|
||||||
|
@ -7,117 +7,42 @@ import (
|
|||||||
|
|
||||||
func Test_read_object_as_any(t *testing.T) {
|
func Test_read_object_as_any(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString(`{"a":"b","c":"d"}`)
|
any := Get([]byte(`{"a":"b","c":"d"}`))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal(`{"a":"b","c":"d"}`, any.ToString())
|
should.Equal(`{"a":"b","c":"d"}`, any.ToString())
|
||||||
// partial parse
|
// partial parse
|
||||||
should.Equal("b", any.Get("a").ToString())
|
should.Equal("b", any.Get("a").ToString())
|
||||||
should.Equal("d", any.Get("c").ToString())
|
should.Equal("d", any.Get("c").ToString())
|
||||||
should.Equal(2, len(any.Keys()))
|
should.Equal(2, len(any.Keys()))
|
||||||
any, err = UnmarshalAnyFromString(`{"a":"b","c":"d"}`)
|
any = Get([]byte(`{"a":"b","c":"d"}`))
|
||||||
// full parse
|
// full parse
|
||||||
should.Equal(2, len(any.Keys()))
|
should.Equal(2, len(any.Keys()))
|
||||||
should.Equal(2, any.Size())
|
should.Equal(2, any.Size())
|
||||||
should.True(any.ToBool())
|
should.True(any.ToBool())
|
||||||
should.Equal(1, any.ToInt())
|
should.Equal(1, any.ToInt())
|
||||||
}
|
should.Equal(Object, any.ValueType())
|
||||||
|
should.Nil(any.LastError())
|
||||||
func Test_object_any_lazy_iterator(t *testing.T) {
|
should.Equal("b", any.GetObject()["a"].ToString())
|
||||||
should := require.New(t)
|
|
||||||
any, err := UnmarshalAnyFromString(`{"a":"b","c":"d"}`)
|
|
||||||
should.Nil(err)
|
|
||||||
// iterator parse
|
|
||||||
vals := map[string]string{}
|
|
||||||
var k string
|
|
||||||
var v Any
|
|
||||||
next, hasNext := any.IterateObject()
|
|
||||||
should.True(hasNext)
|
|
||||||
|
|
||||||
k, v, hasNext = next()
|
|
||||||
should.True(hasNext)
|
|
||||||
vals[k] = v.ToString()
|
|
||||||
|
|
||||||
// trigger full parse
|
|
||||||
should.Equal(2, len(any.Keys()))
|
|
||||||
|
|
||||||
k, v, hasNext = next()
|
|
||||||
should.False(hasNext)
|
|
||||||
vals[k] = v.ToString()
|
|
||||||
|
|
||||||
should.Equal(map[string]string{"a": "b", "c": "d"}, vals)
|
|
||||||
vals = map[string]string{}
|
|
||||||
for next, hasNext := any.IterateObject(); hasNext; {
|
|
||||||
k, v, hasNext = next()
|
|
||||||
if v.ValueType() == String {
|
|
||||||
vals[k] = v.ToString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
should.Equal(map[string]string{"a": "b", "c": "d"}, vals)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_object_any_with_two_lazy_iterators(t *testing.T) {
|
|
||||||
should := require.New(t)
|
|
||||||
any, err := UnmarshalAnyFromString(`{"a":"b","c":"d","e":"f"}`)
|
|
||||||
should.Nil(err)
|
|
||||||
var k string
|
|
||||||
var v Any
|
|
||||||
next1, hasNext1 := any.IterateObject()
|
|
||||||
next2, hasNext2 := any.IterateObject()
|
|
||||||
should.True(hasNext1)
|
|
||||||
k, v, hasNext1 = next1()
|
|
||||||
should.True(hasNext1)
|
|
||||||
should.Equal("a", k)
|
|
||||||
should.Equal("b", v.ToString())
|
|
||||||
|
|
||||||
should.True(hasNext2)
|
|
||||||
k, v, hasNext2 = next2()
|
|
||||||
should.True(hasNext2)
|
|
||||||
should.Equal("a", k)
|
|
||||||
should.Equal("b", v.ToString())
|
|
||||||
|
|
||||||
k, v, hasNext1 = next1()
|
|
||||||
should.True(hasNext1)
|
|
||||||
should.Equal("c", k)
|
|
||||||
should.Equal("d", v.ToString())
|
|
||||||
|
|
||||||
k, v, hasNext2 = next2()
|
|
||||||
should.True(hasNext2)
|
|
||||||
should.Equal("c", k)
|
|
||||||
should.Equal("d", v.ToString())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_object_lazy_any_get(t *testing.T) {
|
func Test_object_lazy_any_get(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString(`{"a":{"b":{"c":"d"}}}`)
|
any := Get([]byte(`{"a":{"b":{"c":"d"}}}`))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal("d", any.Get("a", "b", "c").ToString())
|
should.Equal("d", any.Get("a", "b", "c").ToString())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_object_lazy_any_get_all(t *testing.T) {
|
func Test_object_lazy_any_get_all(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString(`{"a":[0],"b":[1]}`)
|
any := Get([]byte(`{"a":[0],"b":[1]}`))
|
||||||
should.Nil(err)
|
|
||||||
should.Contains(any.Get('*', 0).ToString(), `"a":0`)
|
should.Contains(any.Get('*', 0).ToString(), `"a":0`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_object_lazy_any_get_invalid(t *testing.T) {
|
func Test_object_lazy_any_get_invalid(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString(`{}`)
|
any := Get([]byte(`{}`))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal(Invalid, any.Get("a", "b", "c").ValueType())
|
should.Equal(Invalid, any.Get("a", "b", "c").ValueType())
|
||||||
should.Equal(Invalid, any.Get(1).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"}}}`)
|
|
||||||
should.Nil(err)
|
|
||||||
any.GetObject()["a"] = WrapInt64(1)
|
|
||||||
str, err := MarshalToString(any)
|
|
||||||
should.Nil(err)
|
|
||||||
should.Equal(`{"a":1}`, str)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_wrap_object(t *testing.T) {
|
func Test_wrap_object(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
type TestObject struct {
|
type TestObject struct {
|
||||||
@ -128,17 +53,6 @@ func Test_wrap_object(t *testing.T) {
|
|||||||
should.Equal("hello", any.Get("Field1").ToString())
|
should.Equal("hello", any.Get("Field1").ToString())
|
||||||
any = Wrap(TestObject{"hello", "world"})
|
any = Wrap(TestObject{"hello", "world"})
|
||||||
should.Equal(2, any.Size())
|
should.Equal(2, any.Size())
|
||||||
any = Wrap(TestObject{"hello", "world"})
|
|
||||||
vals := map[string]string{}
|
|
||||||
var k string
|
|
||||||
var v Any
|
|
||||||
for next, hasNext := any.IterateObject(); hasNext; {
|
|
||||||
k, v, hasNext = next()
|
|
||||||
if v.ValueType() == String {
|
|
||||||
vals[k] = v.ToString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
should.Equal(map[string]string{"Field1": "hello"}, vals)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_any_within_struct(t *testing.T) {
|
func Test_any_within_struct(t *testing.T) {
|
||||||
|
@ -7,15 +7,14 @@ import (
|
|||||||
|
|
||||||
func Test_read_string_as_any(t *testing.T) {
|
func Test_read_string_as_any(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any, err := UnmarshalAnyFromString(`"hello"`)
|
any := Get([]byte(`"hello"`))
|
||||||
should.Nil(err)
|
|
||||||
should.Equal("hello", any.ToString())
|
should.Equal("hello", any.ToString())
|
||||||
should.True(any.ToBool())
|
should.True(any.ToBool())
|
||||||
any, err = UnmarshalAnyFromString(`" "`)
|
any = Get([]byte(`" "`))
|
||||||
should.False(any.ToBool())
|
should.False(any.ToBool())
|
||||||
any, err = UnmarshalAnyFromString(`"false"`)
|
any = Get([]byte(`"false"`))
|
||||||
should.False(any.ToBool())
|
should.False(any.ToBool())
|
||||||
any, err = UnmarshalAnyFromString(`"123"`)
|
any = Get([]byte(`"123"`))
|
||||||
should.Equal(123, any.ToInt())
|
should.Equal(123, any.ToInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user