From 987ce709e589068acb7101e5f3a777d908e33292 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 30 Sep 2019 17:23:23 +0800 Subject: [PATCH] add UnmarshalJSON for gtime; add ineterface MapStrAny support for gjson.New --- .example/database/gdb/mysql/gdb_value.go | 19 ++++++++----------- .../garray_z_unit_sorted_any_array_test.go | 6 +++++- container/gmap/gmap_hash_int_any_map.go | 11 +++++++++++ container/gmap/gmap_hash_int_int_map.go | 12 ++++++++++++ container/gmap/gmap_hash_int_str_map.go | 11 +++++++++++ container/gmap/gmap_hash_str_any_map.go | 5 +++++ container/gmap/gmap_hash_str_int_map.go | 11 +++++++++++ container/gmap/gmap_hash_str_str_map.go | 11 +++++++++++ encoding/gjson/gjson_api_new_load.go | 8 ++------ encoding/gjson/gjson_z_unit_basic_test.go | 12 ++++++++++++ test/gtest/gtest.go | 8 ++++---- util/gconv/gconv_map.go | 8 ++++++++ util/gconv/gconv_time.go | 3 +++ 13 files changed, 103 insertions(+), 22 deletions(-) diff --git a/.example/database/gdb/mysql/gdb_value.go b/.example/database/gdb/mysql/gdb_value.go index 969c3a2d7..15581ec19 100644 --- a/.example/database/gdb/mysql/gdb_value.go +++ b/.example/database/gdb/mysql/gdb_value.go @@ -2,26 +2,23 @@ package main import ( "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/os/gtime" ) func main() { db := g.DB() db.SetDebug(true) - //type User struct { - // Uid int - // Name *gvar.Var - //} + type User struct { + Id int + Name *gtime.Time + } - //user := new(User) - ////user.Name = g.NewVar("john") - //g.Dump(gconv.Map(user)) - - _, e := db.Table("test").Data(g.Map{ - "name": nil, - }).Update() + user := new(User) + e := db.Table("test").Where("id", 10000).Struct(user) if e != nil { panic(e) } + g.Dump(user) } diff --git a/container/garray/garray_z_unit_sorted_any_array_test.go b/container/garray/garray_z_unit_sorted_any_array_test.go index 32305bda2..658cb5c15 100644 --- a/container/garray/garray_z_unit_sorted_any_array_test.go +++ b/container/garray/garray_z_unit_sorted_any_array_test.go @@ -567,6 +567,10 @@ func TestSortedArray_Json(t *testing.T) { err = json.Unmarshal(b, user) gtest.Assert(err, nil) gtest.Assert(user.Name, data["Name"]) - gtest.Assert(user.Scores, data["Scores"]) + gtest.AssertNE(user.Scores, nil) + gtest.Assert(user.Scores.Len(), 3) + gtest.AssertIN(user.Scores.PopLeft(), data["Scores"]) + gtest.AssertIN(user.Scores.PopLeft(), data["Scores"]) + gtest.AssertIN(user.Scores.PopLeft(), data["Scores"]) }) } diff --git a/container/gmap/gmap_hash_int_any_map.go b/container/gmap/gmap_hash_int_any_map.go index 465610627..5cfc29850 100644 --- a/container/gmap/gmap_hash_int_any_map.go +++ b/container/gmap/gmap_hash_int_any_map.go @@ -75,6 +75,17 @@ func (m *IntAnyMap) Map() map[int]interface{} { return data } +// MapStrAny returns a copy of the data of the map as map[string]interface{}. +func (m *IntAnyMap) MapStrAny() map[string]interface{} { + m.mu.RLock() + data := make(map[string]interface{}, len(m.data)) + for k, v := range m.data { + data[gconv.String(k)] = v + } + m.mu.RUnlock() + return data +} + // MapCopy returns a copy of the data of the hash map. func (m *IntAnyMap) MapCopy() map[int]interface{} { m.mu.RLock() diff --git a/container/gmap/gmap_hash_int_int_map.go b/container/gmap/gmap_hash_int_int_map.go index de178ec39..b2d7b9d6d 100644 --- a/container/gmap/gmap_hash_int_int_map.go +++ b/container/gmap/gmap_hash_int_int_map.go @@ -8,6 +8,7 @@ package gmap import ( "encoding/json" + "github.com/gogf/gf/util/gconv" "github.com/gogf/gf/internal/empty" @@ -72,6 +73,17 @@ func (m *IntIntMap) Map() map[int]int { return data } +// MapStrAny returns a copy of the data of the map as map[string]interface{}. +func (m *IntIntMap) MapStrAny() map[string]interface{} { + m.mu.RLock() + data := make(map[string]interface{}, len(m.data)) + for k, v := range m.data { + data[gconv.String(k)] = v + } + m.mu.RUnlock() + return data +} + // MapCopy returns a copy of the data of the hash map. func (m *IntIntMap) MapCopy() map[int]int { m.mu.RLock() diff --git a/container/gmap/gmap_hash_int_str_map.go b/container/gmap/gmap_hash_int_str_map.go index 4da07d542..ce3f53918 100644 --- a/container/gmap/gmap_hash_int_str_map.go +++ b/container/gmap/gmap_hash_int_str_map.go @@ -73,6 +73,17 @@ func (m *IntStrMap) Map() map[int]string { return data } +// MapStrAny returns a copy of the data of the map as map[string]interface{}. +func (m *IntStrMap) MapStrAny() map[string]interface{} { + m.mu.RLock() + data := make(map[string]interface{}, len(m.data)) + for k, v := range m.data { + data[gconv.String(k)] = v + } + m.mu.RUnlock() + return data +} + // MapCopy returns a copy of the data of the hash map. func (m *IntStrMap) MapCopy() map[int]string { m.mu.RLock() diff --git a/container/gmap/gmap_hash_str_any_map.go b/container/gmap/gmap_hash_str_any_map.go index 6a42ae2fc..6ece9ccb3 100644 --- a/container/gmap/gmap_hash_str_any_map.go +++ b/container/gmap/gmap_hash_str_any_map.go @@ -75,6 +75,11 @@ func (m *StrAnyMap) Map() map[string]interface{} { return data } +// MapStrAny returns a copy of the data of the map as map[string]interface{}. +func (m *StrAnyMap) MapStrAny() map[string]interface{} { + return m.Map() +} + // MapCopy returns a copy of the data of the hash map. func (m *StrAnyMap) MapCopy() map[string]interface{} { m.mu.RLock() diff --git a/container/gmap/gmap_hash_str_int_map.go b/container/gmap/gmap_hash_str_int_map.go index 0f6ce98d7..a536e2be5 100644 --- a/container/gmap/gmap_hash_str_int_map.go +++ b/container/gmap/gmap_hash_str_int_map.go @@ -73,6 +73,17 @@ func (m *StrIntMap) Map() map[string]int { return data } +// MapStrAny returns a copy of the data of the map as map[string]interface{}. +func (m *StrIntMap) MapStrAny() map[string]interface{} { + m.mu.RLock() + data := make(map[string]interface{}, len(m.data)) + for k, v := range m.data { + data[k] = v + } + m.mu.RUnlock() + return data +} + // MapCopy returns a copy of the data of the hash map. func (m *StrIntMap) MapCopy() map[string]int { m.mu.RLock() diff --git a/container/gmap/gmap_hash_str_str_map.go b/container/gmap/gmap_hash_str_str_map.go index e2d8f800b..3d0944cea 100644 --- a/container/gmap/gmap_hash_str_str_map.go +++ b/container/gmap/gmap_hash_str_str_map.go @@ -73,6 +73,17 @@ func (m *StrStrMap) Map() map[string]string { return data } +// MapStrAny returns a copy of the data of the map as map[string]interface{}. +func (m *StrStrMap) MapStrAny() map[string]interface{} { + m.mu.RLock() + data := make(map[string]interface{}, len(m.data)) + for k, v := range m.data { + data[k] = v + } + m.mu.RUnlock() + return data +} + // MapCopy returns a copy of the data of the hash map. func (m *StrStrMap) MapCopy() map[string]string { m.mu.RLock() diff --git a/encoding/gjson/gjson_api_new_load.go b/encoding/gjson/gjson_api_new_load.go index 8341ff5c8..52086600b 100644 --- a/encoding/gjson/gjson_api_new_load.go +++ b/encoding/gjson/gjson_api_new_load.go @@ -51,9 +51,7 @@ func New(data interface{}, safe ...bool) *Json { kind = rv.Kind() } switch kind { - case reflect.Slice: - fallthrough - case reflect.Array: + case reflect.Slice, reflect.Array: i := interface{}(nil) i = gconv.Interfaces(data) j = &Json{ @@ -61,9 +59,7 @@ func New(data interface{}, safe ...bool) *Json { c: byte(gDEFAULT_SPLIT_CHAR), vc: false, } - case reflect.Map: - fallthrough - case reflect.Struct: + case reflect.Map, reflect.Struct: i := interface{}(nil) i = gconv.Map(data, "json") j = &Json{ diff --git a/encoding/gjson/gjson_z_unit_basic_test.go b/encoding/gjson/gjson_z_unit_basic_test.go index 35b11d734..aa767298c 100644 --- a/encoding/gjson/gjson_z_unit_basic_test.go +++ b/encoding/gjson/gjson_z_unit_basic_test.go @@ -7,6 +7,7 @@ package gjson_test import ( + "github.com/gogf/gf/container/gmap" "testing" "github.com/gogf/gf/encoding/gjson" @@ -22,6 +23,17 @@ func Test_New(t *testing.T) { gtest.Assert(j.Get("m"), g.Map{"k": "v"}) gtest.Assert(j.Get("a"), g.Slice{1, 2, 3}) }) + + gtest.Case(t, func() { + m := gmap.NewAnyAnyMapFrom(g.MapAnyAny{ + "k1": "v1", + "k2": "v2", + }) + j := gjson.New(m) + gtest.Assert(j.Get("k1"), "v1") + gtest.Assert(j.Get("k2"), "v2") + gtest.Assert(j.Get("k3"), nil) + }) } func Test_Valid(t *testing.T) { diff --git a/test/gtest/gtest.go b/test/gtest/gtest.go index 575ee3326..489e62240 100644 --- a/test/gtest/gtest.go +++ b/test/gtest/gtest.go @@ -200,8 +200,8 @@ func AssertIN(value, expect interface{}) { expectKind := reflect.ValueOf(expect).Kind() switch expectKind { case reflect.Slice, reflect.Array: - expectSlice := gconv.Interfaces(expect) - for _, v1 := range gconv.Interfaces(value) { + expectSlice := gconv.Strings(expect) + for _, v1 := range gconv.Strings(value) { result := false for _, v2 := range expectSlice { if v1 == v2 { @@ -231,9 +231,9 @@ func AssertNI(value, expect interface{}) { expectKind := reflect.ValueOf(expect).Kind() switch expectKind { case reflect.Slice, reflect.Array: - for _, v1 := range gconv.Interfaces(value) { + for _, v1 := range gconv.Strings(value) { result := true - for _, v2 := range gconv.Interfaces(expect) { + for _, v2 := range gconv.Strings(expect) { if v1 == v2 { result = false break diff --git a/util/gconv/gconv_map.go b/util/gconv/gconv_map.go index 5954fdd49..6d89e2e6c 100644 --- a/util/gconv/gconv_map.go +++ b/util/gconv/gconv_map.go @@ -15,6 +15,11 @@ import ( "github.com/gogf/gf/internal/utilstr" ) +// Interface support for package gmap. +type apiMapStrAny interface { + MapStrAny() map[string]interface{} +} + // Map converts any variable to map[string]interface{}. // // If the parameter is not a map/struct/*struct type, then the conversion will fail and returns nil. @@ -103,6 +108,9 @@ func Map(value interface{}, tags ...string) map[string]interface{} { m[String(k.Interface())] = rv.MapIndex(k).Interface() } case reflect.Struct: + if v, ok := value.(apiMapStrAny); ok { + return v.MapStrAny() + } rt := rv.Type() name := "" tagArray := structTagPriority diff --git a/util/gconv/gconv_time.go b/util/gconv/gconv_time.go index e9fbd04e1..ecba490d1 100644 --- a/util/gconv/gconv_time.go +++ b/util/gconv/gconv_time.go @@ -38,6 +38,9 @@ func Duration(i interface{}) time.Duration { // If no given, it converts using gtime.NewFromTimeStamp if is numeric, // or using gtime.StrToTime if is string. func GTime(i interface{}, format ...string) *gtime.Time { + if i == nil { + return nil + } s := String(i) if len(s) == 0 { return gtime.New()