mirror of
https://github.com/json-iterator/go.git
synced 2025-04-14 11:18:49 +02:00
#61 remove internal buffer from objectAny
This commit is contained in:
parent
15c92d48df
commit
02cf6a73cc
@ -179,12 +179,11 @@ func (any *objectLazyAny) GetInterface() interface{} {
|
|||||||
type objectAny struct {
|
type objectAny struct {
|
||||||
baseAny
|
baseAny
|
||||||
err error
|
err error
|
||||||
cache map[string]Any
|
|
||||||
val reflect.Value
|
val reflect.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func wrapStruct(val interface{}) *objectAny {
|
func wrapStruct(val interface{}) *objectAny {
|
||||||
return &objectAny{baseAny{}, nil, nil, reflect.ValueOf(val)}
|
return &objectAny{baseAny{}, nil, reflect.ValueOf(val)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectAny) ValueType() ValueType {
|
func (any *objectAny) ValueType() ValueType {
|
||||||
@ -194,51 +193,51 @@ func (any *objectAny) ValueType() ValueType {
|
|||||||
func (any *objectAny) Parse() *Iterator {
|
func (any *objectAny) Parse() *Iterator {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
//
|
||||||
func (any *objectAny) fillCacheUntil(target string) Any {
|
//func (any *objectAny) fillCacheUntil(target string) Any {
|
||||||
if any.cache == nil {
|
// if any.cache == nil {
|
||||||
any.cache = map[string]Any{}
|
// any.cache = map[string]Any{}
|
||||||
}
|
// }
|
||||||
element, found := any.cache[target]
|
// element, found := any.cache[target]
|
||||||
if found {
|
// if found {
|
||||||
return element
|
// return element
|
||||||
}
|
// }
|
||||||
for i := len(any.cache); i < any.val.NumField(); i++ {
|
// for i := len(any.cache); i < any.val.NumField(); i++ {
|
||||||
field := any.val.Field(i)
|
// field := any.val.Field(i)
|
||||||
fieldName := any.val.Type().Field(i).Name
|
// fieldName := any.val.Type().Field(i).Name
|
||||||
var element Any
|
// var element Any
|
||||||
if field.CanInterface() {
|
// if field.CanInterface() {
|
||||||
element = Wrap(field.Interface())
|
// element = Wrap(field.Interface())
|
||||||
} else {
|
// } else {
|
||||||
element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", fieldName, any.cache)}
|
// element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", fieldName, any.cache)}
|
||||||
}
|
// }
|
||||||
any.cache[fieldName] = element
|
// any.cache[fieldName] = element
|
||||||
if fieldName == target {
|
// if fieldName == target {
|
||||||
return element
|
// return element
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return nil
|
// return nil
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
func (any *objectAny) fillCache() {
|
//func (any *objectAny) fillCache() {
|
||||||
if any.cache == nil {
|
// if any.cache == nil {
|
||||||
any.cache = map[string]Any{}
|
// any.cache = map[string]Any{}
|
||||||
}
|
// }
|
||||||
if len(any.cache) == any.val.NumField() {
|
// if len(any.cache) == any.val.NumField() {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
for i := 0; i < any.val.NumField(); i++ {
|
// for i := 0; i < any.val.NumField(); i++ {
|
||||||
field := any.val.Field(i)
|
// field := any.val.Field(i)
|
||||||
fieldName := any.val.Type().Field(i).Name
|
// fieldName := any.val.Type().Field(i).Name
|
||||||
var element Any
|
// var element Any
|
||||||
if field.CanInterface() {
|
// if field.CanInterface() {
|
||||||
element = Wrap(field.Interface())
|
// element = Wrap(field.Interface())
|
||||||
} else {
|
// } else {
|
||||||
element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", fieldName, any.cache)}
|
// element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", fieldName, any.cache)}
|
||||||
}
|
// }
|
||||||
any.cache[fieldName] = element
|
// any.cache[fieldName] = element
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
func (any *objectAny) LastError() error {
|
func (any *objectAny) LastError() error {
|
||||||
return any.err
|
return any.err
|
||||||
@ -305,85 +304,72 @@ func (any *objectAny) ToFloat64() float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectAny) ToString() string {
|
func (any *objectAny) ToString() string {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
str, err := MarshalToString(any.val.Interface())
|
str, err := MarshalToString(any.val.Interface())
|
||||||
any.err = err
|
any.err = err
|
||||||
return str
|
return str
|
||||||
} else {
|
|
||||||
any.fillCache()
|
|
||||||
str, err := MarshalToString(any.cache)
|
|
||||||
any.err = err
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectAny) Get(path ...interface{}) Any {
|
func (any *objectAny) 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)
|
field := any.val.FieldByName(firstPath)
|
||||||
if element == nil {
|
if !field.IsValid() {
|
||||||
element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)}
|
return newInvalidAny(path)
|
||||||
}
|
}
|
||||||
|
return Wrap(field.Interface())
|
||||||
case int32:
|
case int32:
|
||||||
if '*' == firstPath {
|
if '*' == firstPath {
|
||||||
any.fillCache()
|
|
||||||
mappedAll := map[string]Any{}
|
mappedAll := map[string]Any{}
|
||||||
for key, value := range any.cache {
|
for i := 0; i < any.val.NumField(); i++ {
|
||||||
mapped := value.Get(path[1:]...)
|
field := any.val.Field(i)
|
||||||
|
if field.CanInterface() {
|
||||||
|
mapped := Wrap(field.Interface()).Get(path[1:]...)
|
||||||
if mapped.ValueType() != Invalid {
|
if mapped.ValueType() != Invalid {
|
||||||
mappedAll[key] = mapped
|
mappedAll[any.val.Type().Field(i).Name] = mapped
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 *objectAny) Keys() []string {
|
func (any *objectAny) Keys() []string {
|
||||||
any.fillCache()
|
keys := make([]string, 0, any.val.NumField())
|
||||||
keys := make([]string, 0, len(any.cache))
|
for i := 0; i < any.val.NumField(); i++ {
|
||||||
for key := range any.cache {
|
keys = append(keys, any.val.Type().Field(i).Name)
|
||||||
keys = append(keys, key)
|
|
||||||
}
|
}
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectAny) Size() int {
|
func (any *objectAny) Size() int {
|
||||||
any.fillCache()
|
return any.val.NumField()
|
||||||
return len(any.cache)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectAny) GetObject() map[string]Any {
|
func (any *objectAny) GetObject() map[string]Any {
|
||||||
any.fillCache()
|
object := map[string]Any{}
|
||||||
return any.cache
|
for i := 0; i < any.val.NumField(); i++ {
|
||||||
|
field := any.val.Field(i)
|
||||||
|
if field.CanInterface() {
|
||||||
|
object[any.val.Type().Field(i).Name] = Wrap(field.Interface())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return object
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectAny) WriteTo(stream *Stream) {
|
func (any *objectAny) WriteTo(stream *Stream) {
|
||||||
if len(any.cache) == 0 {
|
|
||||||
// nothing has been parsed yet
|
|
||||||
stream.WriteVal(any.val)
|
stream.WriteVal(any.val)
|
||||||
} else {
|
|
||||||
any.fillCache()
|
|
||||||
stream.WriteVal(any.cache)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *objectAny) GetInterface() interface{} {
|
func (any *objectAny) GetInterface() interface{} {
|
||||||
any.fillCache()
|
return any.val.Interface()
|
||||||
return any.cache
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type mapAny struct {
|
type mapAny struct {
|
||||||
|
@ -2,6 +2,7 @@ package jsoniter
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stringAny struct {
|
type stringAny struct {
|
||||||
@ -9,6 +10,13 @@ type stringAny struct {
|
|||||||
val string
|
val string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (any *stringAny) Get(path ...interface{}) Any {
|
||||||
|
if len(path) == 0 {
|
||||||
|
return any
|
||||||
|
}
|
||||||
|
return &invalidAny{baseAny{}, fmt.Errorf("Get %v from simple value", path)}
|
||||||
|
}
|
||||||
|
|
||||||
func (any *stringAny) Parse() *Iterator {
|
func (any *stringAny) Parse() *Iterator {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ 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())
|
||||||
|
should.Equal(`{"Field1":"hello"}`, any.Get('*').ToString())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_any_within_struct(t *testing.T) {
|
func Test_any_within_struct(t *testing.T) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user