From 10a1fb87621fe2b32cf4ce1ac7792bc824d9c8ef Mon Sep 17 00:00:00 2001 From: Tao Wen Date: Sat, 28 Jan 2017 23:11:29 +0800 Subject: [PATCH] wrap map --- feature_any.go | 13 ++++++++++++- feature_any_object.go | 38 ++++++++++++++++++++++++++++++++++++-- jsoniter_map_test.go | 19 +++++++++++++++++++ 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/feature_any.go b/feature_any.go index 1871ac1..8013234 100644 --- a/feature_any.go +++ b/feature_any.go @@ -80,12 +80,17 @@ func WrapString(val string) Any { } func Wrap(val interface{}) Any { + if val == nil { + return &nilAny{} + } type_ := reflect.TypeOf(val) switch type_.Kind() { case reflect.Slice: return wrapArray(val) case reflect.Struct: return wrapStruct(val) + case reflect.Map: + return wrapMap(val) case reflect.String: return WrapString(val.(string)) case reflect.Int: @@ -112,8 +117,14 @@ func Wrap(val interface{}) Any { return WrapFloat64(float64(val.(float32))) case reflect.Float64: return WrapFloat64(val.(float64)) + case reflect.Bool: + if val.(bool) == true { + return &trueAny{} + } else { + return &falseAny{} + } } - return nil + return &invalidAny{baseAny{}, fmt.Errorf("unsupported type: %v", type_)} } func (iter *Iterator) ReadAny() Any { diff --git a/feature_any_object.go b/feature_any_object.go index 2aa5949..0b858d2 100644 --- a/feature_any_object.go +++ b/feature_any_object.go @@ -360,6 +360,9 @@ func (any *objectAny) fillCache() { if any.cache == nil { any.cache = map[string]Any{} } + if len(any.cache) == any.val.NumField() { + return + } for i := 0; i < any.val.NumField(); i++ { field := any.val.Field(i) fieldName := any.val.Type().Field(i).Name @@ -549,7 +552,6 @@ func (any *objectAny) GetInterface() interface{} { return any.cache } - type mapAny struct { baseAny err error @@ -593,6 +595,17 @@ func (any *mapAny) fillCacheUntil(target string) Any { } func (any *mapAny) fillCache() { + if any.cache == nil { + any.cache = map[string]Any{} + } + if len(any.cache) == len(any.val.MapKeys()) { + return + } + for _, key := range any.val.MapKeys() { + keyAsStr := key.String() + element := Wrap(any.val.MapIndex(key).Interface()) + any.cache[keyAsStr] = element + } } func (any *mapAny) LastError() error { @@ -705,7 +718,28 @@ func (any *mapAny) Size() int { } func (any *mapAny) IterateObject() (func() (string, Any, bool), bool) { - return nil, false + 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 { diff --git a/jsoniter_map_test.go b/jsoniter_map_test.go index 44dc9bc..112c4a9 100644 --- a/jsoniter_map_test.go +++ b/jsoniter_map_test.go @@ -24,6 +24,25 @@ func Test_read_map_of_interface(t *testing.T) { should.Equal(map[string]interface{}{"hello": "world"}, iter.Read()) } +func Test_wrap_map(t *testing.T) { + should := require.New(t) + any := Wrap(map[string]string{"Field1": "hello"}) + should.Equal("hello", any.Get("Field1").ToString()) + any = Wrap(map[string]string{"Field1": "hello"}) + 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) +} + func Test_write_val_map(t *testing.T) { should := require.New(t) val := map[string]string{"1": "2"}