From 3fd4cbbbfd98f5e6d354debc35bfd44e4a8abcfb Mon Sep 17 00:00:00 2001 From: John Date: Mon, 29 Jul 2019 19:52:05 +0800 Subject: [PATCH] add MapStruct/MapStructDeep/MapStructs/MapStructsDeep functions for gconv --- g/encoding/gjson/gjson_api.go | 56 ++++- g/encoding/gjson/gjson_api_new_load.go | 9 +- g/test/gtest/gtest.go | 10 +- g/util/gconv/gconv_map.go | 119 ++++++++++ g/util/gconv/gconv_slice.go | 20 +- g/util/gconv/gconv_struct.go | 16 +- g/util/gconv/gconv_z_unit_map_test.go | 280 +++++++++++++++++++++-- g/util/gconv/gconv_z_unit_struct_test.go | 78 ++++++- geg/other/config.toml | 14 ++ geg/other/test.go | 24 +- 10 files changed, 570 insertions(+), 56 deletions(-) create mode 100644 geg/other/config.toml diff --git a/g/encoding/gjson/gjson_api.go b/g/encoding/gjson/gjson_api.go index 04854860a..a1adf7f8a 100644 --- a/g/encoding/gjson/gjson_api.go +++ b/g/encoding/gjson/gjson_api.go @@ -299,6 +299,22 @@ func (j *Json) GetStructsDeep(pattern string, pointer interface{}, mapping ...ma return gconv.StructsDeep(j.Get(pattern), pointer, mapping...) } +func (j *Json) GetMapStruct(pattern string, pointer interface{}, mapping ...map[string]string) error { + return gconv.MapStruct(j.Get(pattern), pointer, mapping...) +} + +func (j *Json) GetMapStructDeep(pattern string, pointer interface{}, mapping ...map[string]string) error { + return gconv.MapStructDeep(j.Get(pattern), pointer, mapping...) +} + +func (j *Json) GetMapStructs(pattern string, pointer interface{}, mapping ...map[string]string) error { + return gconv.MapStructs(j.Get(pattern), pointer, mapping...) +} + +func (j *Json) GetMapStructsDeep(pattern string, pointer interface{}, mapping ...map[string]string) error { + return gconv.MapStructsDeep(j.Get(pattern), pointer, mapping...) +} + // GetToStruct is alias of GetStruct. // Deprecated. func (j *Json) GetToStruct(pattern string, pointer interface{}, mapping ...map[string]string) error { @@ -323,28 +339,52 @@ func (j *Json) ToArray() []interface{} { // ToStruct converts current Json object to specified object. // The should be a pointer type. -func (j *Json) ToStruct(pointer interface{}) error { +func (j *Json) ToStruct(pointer interface{}, mapping ...map[string]string) error { j.mu.RLock() defer j.mu.RUnlock() - return gconv.Struct(*(j.p), pointer) + return gconv.Struct(*(j.p), pointer, mapping...) } -func (j *Json) ToStructDeep(pointer interface{}) error { +func (j *Json) ToStructDeep(pointer interface{}, mapping ...map[string]string) error { j.mu.RLock() defer j.mu.RUnlock() - return gconv.StructDeep(*(j.p), pointer) + return gconv.StructDeep(*(j.p), pointer, mapping...) } -func (j *Json) ToStructs(pointer interface{}) error { +func (j *Json) ToStructs(pointer interface{}, mapping ...map[string]string) error { j.mu.RLock() defer j.mu.RUnlock() - return gconv.Structs(*(j.p), pointer) + return gconv.Structs(*(j.p), pointer, mapping...) } -func (j *Json) ToStructsDeep(pointer interface{}) error { +func (j *Json) ToStructsDeep(pointer interface{}, mapping ...map[string]string) error { j.mu.RLock() defer j.mu.RUnlock() - return gconv.StructsDeep(*(j.p), pointer) + return gconv.StructsDeep(*(j.p), pointer, mapping...) +} + +func (j *Json) ToMapStruct(pointer interface{}, mapping ...map[string]string) error { + j.mu.RLock() + defer j.mu.RUnlock() + return gconv.MapStruct(*(j.p), pointer, mapping...) +} + +func (j *Json) ToMapStructDeep(pointer interface{}, mapping ...map[string]string) error { + j.mu.RLock() + defer j.mu.RUnlock() + return gconv.MapStructDeep(*(j.p), pointer, mapping...) +} + +func (j *Json) ToMapStructs(pointer interface{}, mapping ...map[string]string) error { + j.mu.RLock() + defer j.mu.RUnlock() + return gconv.MapStructs(*(j.p), pointer, mapping...) +} + +func (j *Json) ToMapStructsDeep(pointer interface{}, mapping ...map[string]string) error { + j.mu.RLock() + defer j.mu.RUnlock() + return gconv.MapStructsDeep(*(j.p), pointer, mapping...) } // Dump prints current Json object with more manually readable. diff --git a/g/encoding/gjson/gjson_api_new_load.go b/g/encoding/gjson/gjson_api_new_load.go index 220790e69..66e3ff3de 100644 --- a/g/encoding/gjson/gjson_api_new_load.go +++ b/g/encoding/gjson/gjson_api_new_load.go @@ -128,9 +128,14 @@ func DecodeToJson(data interface{}, unsafe ...bool) (*Json, error) { } } -// Load loads content from specified file , -// and creates a Json object from its content. +// Load loads content from specified file . +// It automatically checks the content type, creates and returns a Json object from the content. func Load(path string, unsafe ...bool) (*Json, error) { + if p, err := gfile.Search(path); err != nil { + return nil, err + } else { + path = p + } return doLoadContent(gfile.Ext(path), gfcache.GetBinContents(path), unsafe...) } diff --git a/g/test/gtest/gtest.go b/g/test/gtest/gtest.go index 61aaeaccb..8f00f3055 100644 --- a/g/test/gtest/gtest.go +++ b/g/test/gtest/gtest.go @@ -209,7 +209,8 @@ func AssertLE(value, expect interface{}) { // TODO map support. func AssertIN(value, expect interface{}) { passed := true - switch reflect.ValueOf(expect).Kind() { + expectKind := reflect.ValueOf(expect).Kind() + switch expectKind { case reflect.Slice, reflect.Array: expectSlice := gconv.Interfaces(expect) for _, v1 := range gconv.Interfaces(value) { @@ -225,6 +226,8 @@ func AssertIN(value, expect interface{}) { break } } + default: + panic(fmt.Sprintf(`[ASSERT] INVALID EXPECT VALUE TYPE: %v`, expectKind)) } if !passed { panic(fmt.Sprintf(`[ASSERT] EXPECT %v IN %v`, value, expect)) @@ -237,7 +240,8 @@ func AssertIN(value, expect interface{}) { // TODO map support. func AssertNI(value, expect interface{}) { passed := true - switch reflect.ValueOf(expect).Kind() { + expectKind := reflect.ValueOf(expect).Kind() + switch expectKind { case reflect.Slice, reflect.Array: for _, v1 := range gconv.Interfaces(value) { result := true @@ -252,6 +256,8 @@ func AssertNI(value, expect interface{}) { break } } + default: + panic(fmt.Sprintf(`[ASSERT] INVALID EXPECT VALUE TYPE: %v`, expectKind)) } if !passed { panic(fmt.Sprintf(`[ASSERT] EXPECT %v NOT IN %v`, value, expect)) diff --git a/g/util/gconv/gconv_map.go b/g/util/gconv/gconv_map.go index 1d74da30a..56f0b8a92 100644 --- a/g/util/gconv/gconv_map.go +++ b/g/util/gconv/gconv_map.go @@ -7,6 +7,7 @@ package gconv import ( + "errors" "reflect" "strings" @@ -179,3 +180,121 @@ func MapDeep(value interface{}, tags ...string) map[string]interface{} { } return data } + +// MapStruct converts map type variable to another map type variable . +// The elements of should be type of struct/*struct. +func MapStruct(params interface{}, pointer interface{}, mapping ...map[string]string) error { + return doMapStruct(params, pointer, false, mapping...) +} + +// MapStructDeep recursively converts map type variable to another map type variable . +// The elements of should be type of struct/*struct. +func MapStructDeep(params interface{}, pointer interface{}, mapping ...map[string]string) error { + return doMapStruct(params, pointer, true, mapping...) +} + +// doMapStruct converts map type variable to another map type variable . +// The elements of should be type of struct/*struct. +func doMapStruct(params interface{}, pointer interface{}, deep bool, mapping ...map[string]string) error { + paramsRv := reflect.ValueOf(params) + paramsKind := paramsRv.Kind() + if paramsKind == reflect.Ptr { + paramsRv = paramsRv.Elem() + paramsKind = paramsRv.Kind() + } + if paramsKind != reflect.Map { + return errors.New("params should be type of map") + } + + pointerRv := reflect.ValueOf(pointer) + pointerKind := pointerRv.Kind() + for pointerKind == reflect.Ptr { + pointerRv = pointerRv.Elem() + pointerKind = pointerRv.Kind() + } + if pointerKind != reflect.Map { + return errors.New("pointer should be type of map") + } + err := (error)(nil) + paramsKeys := paramsRv.MapKeys() + pointerKeyType := pointerRv.Type().Key() + pointerValueType := pointerRv.Type().Elem() + dataMap := reflect.MakeMapWithSize(pointerRv.Type(), len(paramsKeys)) + for _, key := range paramsKeys { + e := reflect.New(pointerValueType).Elem() + if deep { + if err = StructDeep(paramsRv.MapIndex(key).Interface(), e, mapping...); err != nil { + return err + } + } else { + if err = Struct(paramsRv.MapIndex(key).Interface(), e, mapping...); err != nil { + return err + } + } + dataMap.SetMapIndex( + reflect.ValueOf(Convert(key.Interface(), pointerKeyType.Name())), + e, + ) + } + pointerRv.Set(dataMap) + return nil +} + +// MapStructs converts map type variable to another map type variable . +// The elements of should be type of []struct/[]*struct. +func MapStructs(params interface{}, pointer interface{}, mapping ...map[string]string) error { + return doMapStructs(params, pointer, false, mapping...) +} + +// MapStructsDeep recursively converts map type variable to another map type variable . +// The elements of should be type of []struct/[]*struct. +func MapStructsDeep(params interface{}, pointer interface{}, mapping ...map[string]string) error { + return doMapStructs(params, pointer, true, mapping...) +} + +// doMapStructs converts map type variable to another map type variable . +// The elements of should be type of []struct/[]*struct. +func doMapStructs(params interface{}, pointer interface{}, deep bool, mapping ...map[string]string) error { + paramsRv := reflect.ValueOf(params) + paramsKind := paramsRv.Kind() + if paramsKind == reflect.Ptr { + paramsRv = paramsRv.Elem() + paramsKind = paramsRv.Kind() + } + if paramsKind != reflect.Map { + return errors.New("params should be type of map") + } + + pointerRv := reflect.ValueOf(pointer) + pointerKind := pointerRv.Kind() + for pointerKind == reflect.Ptr { + pointerRv = pointerRv.Elem() + pointerKind = pointerRv.Kind() + } + if pointerKind != reflect.Map { + return errors.New("pointer should be type of map") + } + err := (error)(nil) + paramsKeys := paramsRv.MapKeys() + pointerKeyType := pointerRv.Type().Key() + pointerValueType := pointerRv.Type().Elem() + dataMap := reflect.MakeMapWithSize(pointerRv.Type(), len(paramsKeys)) + for _, key := range paramsKeys { + e := reflect.New(pointerValueType).Elem().Addr() + if deep { + if err = StructsDeep(paramsRv.MapIndex(key).Interface(), e, mapping...); err != nil { + return err + } + } else { + if err = Structs(paramsRv.MapIndex(key).Interface(), e, mapping...); err != nil { + return err + } + } + dataMap.SetMapIndex( + reflect.ValueOf(Convert(key.Interface(), pointerKeyType.Name())), + e.Elem(), + ) + } + pointerRv.Set(dataMap) + return nil +} diff --git a/g/util/gconv/gconv_slice.go b/g/util/gconv/gconv_slice.go index 137754333..6d9ff97d2 100644 --- a/g/util/gconv/gconv_slice.go +++ b/g/util/gconv/gconv_slice.go @@ -351,8 +351,7 @@ func Interfaces(i interface{}) []interface{} { // Finally we use reflection. rv := reflect.ValueOf(i) kind := rv.Kind() - // If it's pointer, find the real type. - if kind == reflect.Ptr { + for kind == reflect.Ptr { rv = rv.Elem() kind = rv.Kind() } @@ -442,14 +441,16 @@ func doStructs(params interface{}, pointer interface{}, deep bool, mapping ...ma if pointer == nil { return errors.New("object pointer cannot be nil") } - pointerRt := reflect.TypeOf(pointer) - if kind := pointerRt.Kind(); kind != reflect.Ptr { - return fmt.Errorf("pointer should be type of pointer, but got: %v", kind) + pointerRv, ok := pointer.(reflect.Value) + if !ok { + pointerRv = reflect.ValueOf(pointer) + if kind := pointerRv.Kind(); kind != reflect.Ptr { + return fmt.Errorf("pointer should be type of pointer, but got: %v", kind) + } } - rv := reflect.ValueOf(params) kind := rv.Kind() - if kind == reflect.Ptr { + for kind == reflect.Ptr { rv = rv.Elem() kind = rv.Kind() } @@ -459,7 +460,7 @@ func doStructs(params interface{}, pointer interface{}, deep bool, mapping ...ma if rv.Len() == 0 { return nil } - array := reflect.MakeSlice(pointerRt.Elem(), rv.Len(), rv.Len()) + array := reflect.MakeSlice(pointerRv.Type().Elem(), rv.Len(), rv.Len()) itemType := array.Index(0).Type() for i := 0; i < rv.Len(); i++ { if itemType.Kind() == reflect.Ptr { @@ -478,7 +479,6 @@ func doStructs(params interface{}, pointer interface{}, deep bool, mapping ...ma } else { // Slice element is not type of pointer. e := reflect.New(itemType).Elem() - if deep { if err = StructDeep(rv.Index(i).Interface(), e, mapping...); err != nil { return err @@ -491,7 +491,7 @@ func doStructs(params interface{}, pointer interface{}, deep bool, mapping ...ma array.Index(i).Set(e) } } - reflect.ValueOf(pointer).Elem().Set(array) + pointerRv.Elem().Set(array) return nil default: return fmt.Errorf("params should be type of slice, but got: %v", kind) diff --git a/g/util/gconv/gconv_struct.go b/g/util/gconv/gconv_struct.go index 0bcff3644..51ae60e52 100644 --- a/g/util/gconv/gconv_struct.go +++ b/g/util/gconv/gconv_struct.go @@ -52,13 +52,13 @@ func Struct(params interface{}, pointer interface{}, mapping ...map[string]strin return errors.New("object pointer cannot be nil") } elem = rv.Elem() - // Auto create struct object. - // For example, if is **User, then is *User, which is a pointer to User. - if elem.Type().Kind() == reflect.Ptr && (!elem.IsValid() || elem.IsNil()) { - e := reflect.New(elem.Type().Elem()).Elem() - elem.Set(e.Addr()) - elem = e - } + } + // Auto create struct object. + // For example, if is **User, then is *User, which is a pointer to User. + if elem.Type().Kind() == reflect.Ptr && (!elem.IsValid() || elem.IsNil()) { + e := reflect.New(elem.Type().Elem()).Elem() + elem.Set(e.Addr()) + elem = e } // It only performs one converting to the same attribute. // doneMap is used to check repeated converting. @@ -150,7 +150,7 @@ func StructDeep(params interface{}, pointer interface{}, mapping ...map[string]s rv = reflect.ValueOf(pointer) } kind := rv.Kind() - if kind == reflect.Ptr { + for kind == reflect.Ptr { rv = rv.Elem() kind = rv.Kind() } diff --git a/g/util/gconv/gconv_z_unit_map_test.go b/g/util/gconv/gconv_z_unit_map_test.go index 34bbd20a4..c40c9e6df 100644 --- a/g/util/gconv/gconv_z_unit_map_test.go +++ b/g/util/gconv/gconv_z_unit_map_test.go @@ -7,10 +7,11 @@ package gconv_test import ( + "testing" + "github.com/gogf/gf/g" "github.com/gogf/gf/g/test/gtest" "github.com/gogf/gf/g/util/gconv" - "testing" ) func Test_Map_Basic(t *testing.T) { @@ -124,21 +125,31 @@ func Test_Map_PrivateAttribute(t *testing.T) { } func Test_Map_StructInherit(t *testing.T) { + type Ids struct { + Id int `json:"id"` + Uid int `json:"uid"` + } + type Base struct { + Ids + CreateTime string `json:"create_time"` + } + type User struct { + Base + Passport string `json:"passport"` + Password string `json:"password"` + Nickname string `json:"nickname"` + } + gtest.Case(t, func() { + user := new(User) + user.Id = 100 + user.Nickname = "john" + user.CreateTime = "2019" + m := gconv.Map(user) + gtest.Assert(m["id"], "") + gtest.Assert(m["nickname"], user.Nickname) + gtest.Assert(m["create_time"], "") + }) gtest.Case(t, func() { - type Ids struct { - Id int `json:"id"` - Uid int `json:"uid"` - } - type Base struct { - Ids - CreateTime string `json:"create_time"` - } - type User struct { - Base - Passport string `json:"passport"` - Password string `json:"password"` - Nickname string `json:"nickname"` - } user := new(User) user.Id = 100 user.Nickname = "john" @@ -149,3 +160,242 @@ func Test_Map_StructInherit(t *testing.T) { gtest.Assert(m["create_time"], user.CreateTime) }) } + +func Test_MapStruct(t *testing.T) { + type User struct { + Id int + Name string + } + params := g.Map{ + "key": g.Map{ + "id": 1, + "name": "john", + }, + } + gtest.Case(t, func() { + m := make(map[string]User) + err := gconv.MapStruct(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 1) + gtest.Assert(m["key"].Id, 1) + gtest.Assert(m["key"].Name, "john") + }) + gtest.Case(t, func() { + m := (map[string]User)(nil) + err := gconv.MapStruct(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 1) + gtest.Assert(m["key"].Id, 1) + gtest.Assert(m["key"].Name, "john") + }) + gtest.Case(t, func() { + m := make(map[string]*User) + err := gconv.MapStruct(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 1) + gtest.Assert(m["key"].Id, 1) + gtest.Assert(m["key"].Name, "john") + }) + gtest.Case(t, func() { + m := (map[string]*User)(nil) + err := gconv.MapStruct(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 1) + gtest.Assert(m["key"].Id, 1) + gtest.Assert(m["key"].Name, "john") + }) +} + +func Test_MapStructDeep(t *testing.T) { + type Ids struct { + Id int + Uid int + } + type Base struct { + Ids + Time string + } + type User struct { + Base + Name string + } + params := g.Map{ + "key": g.Map{ + "id": 1, + "name": "john", + }, + } + gtest.Case(t, func() { + m := (map[string]*User)(nil) + err := gconv.MapStruct(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 1) + gtest.Assert(m["key"].Id, 0) + gtest.Assert(m["key"].Name, "john") + }) + gtest.Case(t, func() { + m := (map[string]*User)(nil) + err := gconv.MapStructDeep(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 1) + gtest.Assert(m["key"].Id, 1) + gtest.Assert(m["key"].Name, "john") + }) +} + +func Test_MapStructs1(t *testing.T) { + type User struct { + Id int + Name int + } + params := g.Map{ + "key1": g.Slice{ + g.Map{"id": 1, "name": "john"}, + g.Map{"id": 2, "name": "smith"}, + }, + "key2": g.Slice{ + g.Map{"id": 3, "name": "green"}, + g.Map{"id": 4, "name": "jim"}, + }, + } + gtest.Case(t, func() { + m := make(map[string][]User) + err := gconv.MapStructs(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 2) + gtest.Assert(m["key1"][0].Id, 1) + gtest.Assert(m["key1"][1].Id, 2) + gtest.Assert(m["key2"][0].Id, 3) + gtest.Assert(m["key2"][1].Id, 4) + }) + gtest.Case(t, func() { + m := (map[string][]User)(nil) + err := gconv.MapStructs(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 2) + gtest.Assert(m["key1"][0].Id, 1) + gtest.Assert(m["key1"][1].Id, 2) + gtest.Assert(m["key2"][0].Id, 3) + gtest.Assert(m["key2"][1].Id, 4) + }) + gtest.Case(t, func() { + m := make(map[string][]*User) + err := gconv.MapStructs(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 2) + gtest.Assert(m["key1"][0].Id, 1) + gtest.Assert(m["key1"][1].Id, 2) + gtest.Assert(m["key2"][0].Id, 3) + gtest.Assert(m["key2"][1].Id, 4) + }) + gtest.Case(t, func() { + m := (map[string][]*User)(nil) + err := gconv.MapStructs(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 2) + gtest.Assert(m["key1"][0].Id, 1) + gtest.Assert(m["key1"][1].Id, 2) + gtest.Assert(m["key2"][0].Id, 3) + gtest.Assert(m["key2"][1].Id, 4) + }) +} + +func Test_MapStructs2(t *testing.T) { + type User struct { + Id int + Name int + } + params := g.MapIntAny{ + 100: g.Slice{ + g.Map{"id": 1, "name": "john"}, + g.Map{"id": 2, "name": "smith"}, + }, + 200: g.Slice{ + g.Map{"id": 3, "name": "green"}, + g.Map{"id": 4, "name": "jim"}, + }, + } + gtest.Case(t, func() { + m := make(map[int][]User) + err := gconv.MapStructs(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 2) + gtest.Assert(m[100][0].Id, 1) + gtest.Assert(m[100][1].Id, 2) + gtest.Assert(m[200][0].Id, 3) + gtest.Assert(m[200][1].Id, 4) + }) + gtest.Case(t, func() { + m := make(map[int][]*User) + err := gconv.MapStructs(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 2) + gtest.Assert(m[100][0].Id, 1) + gtest.Assert(m[100][1].Id, 2) + gtest.Assert(m[200][0].Id, 3) + gtest.Assert(m[200][1].Id, 4) + }) + gtest.Case(t, func() { + m := make(map[string][]*User) + err := gconv.MapStructs(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 2) + gtest.Assert(m["100"][0].Id, 1) + gtest.Assert(m["100"][1].Id, 2) + gtest.Assert(m["200"][0].Id, 3) + gtest.Assert(m["200"][1].Id, 4) + }) +} + +func Test_MapStructsDeep(t *testing.T) { + type Ids struct { + Id int + Uid int + } + type Base struct { + Ids + Time string + } + type User struct { + Base + Name string + } + params := g.MapIntAny{ + 100: g.Slice{ + g.Map{"id": 1, "name": "john"}, + g.Map{"id": 2, "name": "smith"}, + }, + 200: g.Slice{ + g.Map{"id": 3, "name": "green"}, + g.Map{"id": 4, "name": "jim"}, + }, + } + gtest.Case(t, func() { + m := make(map[string][]*User) + err := gconv.MapStructs(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 2) + gtest.Assert(m["100"][0].Id, 0) + gtest.Assert(m["100"][1].Id, 0) + gtest.Assert(m["100"][0].Name, "john") + gtest.Assert(m["100"][1].Name, "smith") + gtest.Assert(m["200"][0].Id, 0) + gtest.Assert(m["200"][1].Id, 0) + gtest.Assert(m["200"][0].Name, "green") + gtest.Assert(m["200"][1].Name, "jim") + }) + gtest.Case(t, func() { + m := make(map[string][]*User) + err := gconv.MapStructsDeep(params, &m) + gtest.Assert(err, nil) + gtest.Assert(len(m), 2) + gtest.Assert(m["100"][0].Id, 1) + gtest.Assert(m["100"][1].Id, 2) + gtest.Assert(m["100"][0].Name, "john") + gtest.Assert(m["100"][1].Name, "smith") + gtest.Assert(m["200"][0].Id, 3) + gtest.Assert(m["200"][1].Id, 4) + gtest.Assert(m["200"][0].Name, "green") + gtest.Assert(m["200"][1].Name, "jim") + }) +} diff --git a/g/util/gconv/gconv_z_unit_struct_test.go b/g/util/gconv/gconv_z_unit_struct_test.go index a424eab2e..aa067ba0e 100644 --- a/g/util/gconv/gconv_z_unit_struct_test.go +++ b/g/util/gconv/gconv_z_unit_struct_test.go @@ -337,17 +337,30 @@ func Test_Struct_PrivateAttribute(t *testing.T) { }) } -func Test_Struct_Deep(t *testing.T) { +func Test_StructDeep1(t *testing.T) { + type Base struct { + Age int + } + type User struct { + Id int + Name string + Base + } + gtest.Case(t, func() { + user := new(User) + params := g.Map{ + "id": 1, + "name": "john", + "age": 18, + } + err := gconv.Struct(params, user) + gtest.Assert(err, nil) + gtest.Assert(user.Id, params["id"]) + gtest.Assert(user.Name, params["name"]) + gtest.Assert(user.Age, 0) + }) gtest.Case(t, func() { - type Base struct { - Age int - } - type User struct { - Id int - Name string - Base - } user := new(User) params := g.Map{ "id": 1, @@ -360,7 +373,54 @@ func Test_Struct_Deep(t *testing.T) { gtest.Assert(user.Name, params["name"]) gtest.Assert(user.Age, params["age"]) }) +} +func Test_StructDeep2(t *testing.T) { + type Ids struct { + Id int + Uid int + } + type Base struct { + Ids + Time string + } + type User struct { + Base + Name string + } + params := g.Map{ + "id": 1, + "uid": 10, + "name": "john", + } + gtest.Case(t, func() { + user := new(User) + err := gconv.Struct(params, user) + gtest.Assert(err, nil) + gtest.Assert(user.Id, 0) + gtest.Assert(user.Uid, 0) + gtest.Assert(user.Name, "john") + }) + + gtest.Case(t, func() { + user := new(User) + err := gconv.StructDeep(params, user) + gtest.Assert(err, nil) + gtest.Assert(user.Id, 1) + gtest.Assert(user.Uid, 10) + gtest.Assert(user.Name, "john") + }) + gtest.Case(t, func() { + user := (*User)(nil) + err := gconv.StructDeep(params, &user) + gtest.Assert(err, nil) + gtest.Assert(user.Id, 1) + gtest.Assert(user.Uid, 10) + gtest.Assert(user.Name, "john") + }) +} + +func Test_StructDeep3(t *testing.T) { gtest.Case(t, func() { type Ids struct { Id int `json:"id"` diff --git a/geg/other/config.toml b/geg/other/config.toml new file mode 100644 index 000000000..72cd2b195 --- /dev/null +++ b/geg/other/config.toml @@ -0,0 +1,14 @@ +# 监控服务主动拉取监控数据配置 +[active-pulling] + # 业务类别 腾讯问诊 订单总数 + [[active-pulling.tencent-inquiry]] + groupId = 3533761 + metricName = "OrderCount" # 监控项名称 + url = "http://ylt.medlinker.com/monitor/ordercount" # 监控数据地址 + interval = "1m" # d:日 h:小时 m:分 s:秒 + # 业务类别 腾讯问诊 超时订单总数 + [[active-pulling.tencent-inquiry]] + groupId = 3533711 + metricName = "TimedOutOrderCount" + url = "http://ylt.medlinker.com/monitor/timedout-ordercount" + interval = "1m" \ No newline at end of file diff --git a/geg/other/test.go b/geg/other/test.go index f71bc27b8..39ac75e4c 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -2,9 +2,29 @@ package main import ( "fmt" + "github.com/gogf/gf/g" + "github.com/gogf/gf/g/encoding/gjson" + "github.com/gogf/gf/g/util/gconv" ) -func main() { - fmt.Println(g.Config().Get("log-path")) +type Item struct { + GroupId int + Interval string + MetricName string + Url string +} + +func main() { + j, err := gjson.Load("config.toml") + if err != nil { + panic(err) + } + m := j.GetMap("active-pulling") + //g.Dump(m) + + newm := make(map[string][]Item) + err = gconv.MapStructs(m, &newm) + fmt.Println(err) + g.Dump(newm) }