mirror of
https://gitee.com/johng/gf.git
synced 2024-12-03 12:47:50 +08:00
improve gconv.Struct for map attribute converting
This commit is contained in:
parent
457d552fa0
commit
f03f56ba4e
@ -548,6 +548,7 @@ func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interfa
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Automatically mapping and filtering the struct attribute.
|
// Automatically mapping and filtering the struct attribute.
|
||||||
|
// TODO struct fields in sequence
|
||||||
data := DataToMapDeep(in.Where)
|
data := DataToMapDeep(in.Where)
|
||||||
if in.Table != "" {
|
if in.Table != "" {
|
||||||
data, _ = db.GetCore().mappingAndFilterData(in.Schema, in.Table, data, true)
|
data, _ = db.GetCore().mappingAndFilterData(in.Schema, in.Table, data, true)
|
||||||
|
@ -273,7 +273,7 @@ func (g *RouterGroup) getPrefix() string {
|
|||||||
return prefix
|
return prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
// doBindRoutersToServer does really registering for the group.
|
// doBindRoutersToServer does really register for the group.
|
||||||
func (g *RouterGroup) doBindRoutersToServer(item *preBindItem) *RouterGroup {
|
func (g *RouterGroup) doBindRoutersToServer(item *preBindItem) *RouterGroup {
|
||||||
var (
|
var (
|
||||||
bindType = item.bindType
|
bindType = item.bindType
|
||||||
@ -289,7 +289,7 @@ func (g *RouterGroup) doBindRoutersToServer(item *preBindItem) *RouterGroup {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
g.server.Logger().Fatalf("invalid pattern: %s", pattern)
|
g.server.Logger().Fatalf("invalid pattern: %s", pattern)
|
||||||
}
|
}
|
||||||
// If there'a already a domain, unset the domain field in the pattern.
|
// If there is already a domain, unset the domain field in the pattern.
|
||||||
if g.domain != nil {
|
if g.domain != nil {
|
||||||
domain = ""
|
domain = ""
|
||||||
}
|
}
|
||||||
|
@ -54,9 +54,8 @@ func (c *Cron) addEntry(pattern string, job func(), singleton bool, name ...stri
|
|||||||
}
|
}
|
||||||
// When you add a scheduled task, you cannot allow it to run.
|
// When you add a scheduled task, you cannot allow it to run.
|
||||||
// It cannot start running when added to gtimer.
|
// It cannot start running when added to gtimer.
|
||||||
// It should start running after the entry is added to the entries map,
|
// It should start running after the entry is added to the Cron entries map, to avoid the task
|
||||||
// to avoid the task from running during adding where the entries
|
// from running during adding where the entries do not have the entry information, which might cause panic.
|
||||||
// does not have the entry information, which might cause panic.
|
|
||||||
entry.entry = gtimer.AddEntry(time.Second, entry.check, singleton, -1, gtimer.StatusStopped)
|
entry.entry = gtimer.AddEntry(time.Second, entry.check, singleton, -1, gtimer.StatusStopped)
|
||||||
c.entries.Set(entry.Name, entry)
|
c.entries.Set(entry.Name, entry)
|
||||||
entry.entry.Start()
|
entry.entry.Start()
|
||||||
@ -70,7 +69,7 @@ func (entry *Entry) IsSingleton() bool {
|
|||||||
|
|
||||||
// SetSingleton sets the entry running in singleton mode.
|
// SetSingleton sets the entry running in singleton mode.
|
||||||
func (entry *Entry) SetSingleton(enabled bool) {
|
func (entry *Entry) SetSingleton(enabled bool) {
|
||||||
entry.entry.SetSingleton(true)
|
entry.entry.SetSingleton(enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTimes sets the times which the entry can run.
|
// SetTimes sets the times which the entry can run.
|
||||||
|
@ -22,10 +22,10 @@ func MapToMap(params interface{}, pointer interface{}, mapping ...map[string]str
|
|||||||
// doMapToMap converts any map type variable `params` to another map type variable `pointer`.
|
// doMapToMap converts any map type variable `params` to another map type variable `pointer`.
|
||||||
//
|
//
|
||||||
// The parameter `params` can be any type of map, like:
|
// The parameter `params` can be any type of map, like:
|
||||||
// map[string]string, map[string]struct, , map[string]*struct, etc.
|
// map[string]string, map[string]struct, map[string]*struct, etc.
|
||||||
//
|
//
|
||||||
// The parameter `pointer` should be type of *map, like:
|
// The parameter `pointer` should be type of *map, like:
|
||||||
// map[int]string, map[string]struct, , map[string]*struct, etc.
|
// map[int]string, map[string]struct, map[string]*struct, etc.
|
||||||
//
|
//
|
||||||
// The optional parameter `mapping` is used for struct attribute to map key mapping, which makes
|
// The optional parameter `mapping` is used for struct attribute to map key mapping, which makes
|
||||||
// sense only if the items of original map `params` is type struct.
|
// sense only if the items of original map `params` is type struct.
|
||||||
@ -54,9 +54,13 @@ func doMapToMap(params interface{}, pointer interface{}, mapping ...map[string]s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
paramsRv reflect.Value
|
paramsRv reflect.Value
|
||||||
paramsKind reflect.Kind
|
paramsKind reflect.Kind
|
||||||
|
keyToAttributeNameMapping map[string]string
|
||||||
)
|
)
|
||||||
|
if len(mapping) > 0 {
|
||||||
|
keyToAttributeNameMapping = mapping[0]
|
||||||
|
}
|
||||||
if v, ok := params.(reflect.Value); ok {
|
if v, ok := params.(reflect.Value); ok {
|
||||||
paramsRv = v
|
paramsRv = v
|
||||||
} else {
|
} else {
|
||||||
@ -113,7 +117,7 @@ func doMapToMap(params interface{}, pointer interface{}, mapping ...map[string]s
|
|||||||
e := reflect.New(pointerValueType).Elem()
|
e := reflect.New(pointerValueType).Elem()
|
||||||
switch pointerValueKind {
|
switch pointerValueKind {
|
||||||
case reflect.Map, reflect.Struct:
|
case reflect.Map, reflect.Struct:
|
||||||
if err = Struct(paramsRv.MapIndex(key).Interface(), e, mapping...); err != nil {
|
if err = doStruct(paramsRv.MapIndex(key).Interface(), e, keyToAttributeNameMapping, ""); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -11,28 +11,41 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Scan automatically calls MapToMap, MapToMaps, Struct or Structs function according to
|
// Scan automatically checks the type of `pointer` and converts `params` to `pointer`. It supports `pointer`
|
||||||
// the type of parameter `pointer` to implement the converting.
|
// with type of `*map/*[]map/*[]*map/*struct/**struct/*[]struct/*[]*struct` for converting.
|
||||||
//
|
//
|
||||||
// It calls function MapToMap if `pointer` is type of *map to do the converting.
|
// It calls function `doMapToMap` internally if `pointer` is type of *map for converting.
|
||||||
// It calls function MapToMaps if `pointer` is type of *[]map/*[]*map to do the converting.
|
// It calls function `doMapToMaps` internally if `pointer` is type of *[]map/*[]*map for converting.
|
||||||
// It calls function Struct if `pointer` is type of *struct/**struct to do the converting.
|
// It calls function `doStruct` internally if `pointer` is type of *struct/**struct for converting.
|
||||||
// It calls function Structs if `pointer` is type of *[]struct/*[]*struct to do the converting.
|
// It calls function `doStructs` internally if `pointer` is type of *[]struct/*[]*struct for converting.
|
||||||
func Scan(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
func Scan(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||||
var (
|
var (
|
||||||
pointerType = reflect.TypeOf(pointer)
|
pointerType reflect.Type
|
||||||
pointerKind = pointerType.Kind()
|
pointerKind reflect.Kind
|
||||||
)
|
)
|
||||||
|
if v, ok := pointer.(reflect.Value); ok {
|
||||||
|
pointerType = v.Type()
|
||||||
|
} else {
|
||||||
|
pointerType = reflect.TypeOf(pointer)
|
||||||
|
}
|
||||||
|
if pointerType == nil {
|
||||||
|
return gerror.NewCode(gerror.CodeInvalidParameter, "parameter pointer should not be nil")
|
||||||
|
}
|
||||||
|
pointerKind = pointerType.Kind()
|
||||||
if pointerKind != reflect.Ptr {
|
if pointerKind != reflect.Ptr {
|
||||||
return gerror.NewCodef(gerror.CodeInvalidParameter, "params should be type of pointer, but got: %v", pointerKind)
|
return gerror.NewCodef(gerror.CodeInvalidParameter, "params should be type of pointer, but got type: %v", pointerKind)
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
pointerElem = pointerType.Elem()
|
pointerElem = pointerType.Elem()
|
||||||
pointerElemKind = pointerElem.Kind()
|
pointerElemKind = pointerElem.Kind()
|
||||||
|
keyToAttributeNameMapping map[string]string
|
||||||
)
|
)
|
||||||
|
if len(mapping) > 0 {
|
||||||
|
keyToAttributeNameMapping = mapping[0]
|
||||||
|
}
|
||||||
switch pointerElemKind {
|
switch pointerElemKind {
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
return MapToMap(params, pointer, mapping...)
|
return doMapToMap(params, pointer, mapping...)
|
||||||
|
|
||||||
case reflect.Array, reflect.Slice:
|
case reflect.Array, reflect.Slice:
|
||||||
var (
|
var (
|
||||||
@ -44,11 +57,13 @@ func Scan(params interface{}, pointer interface{}, mapping ...map[string]string)
|
|||||||
sliceElemKind = sliceElem.Kind()
|
sliceElemKind = sliceElem.Kind()
|
||||||
}
|
}
|
||||||
if sliceElemKind == reflect.Map {
|
if sliceElemKind == reflect.Map {
|
||||||
return MapToMaps(params, pointer, mapping...)
|
return doMapToMaps(params, pointer, mapping...)
|
||||||
}
|
}
|
||||||
return Structs(params, pointer, mapping...)
|
return doStructs(params, pointer, keyToAttributeNameMapping, "")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return Struct(params, pointer, mapping...)
|
|
||||||
|
return doStruct(params, pointer, keyToAttributeNameMapping, "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,11 +31,7 @@ import (
|
|||||||
// in mapping procedure to do the matching.
|
// in mapping procedure to do the matching.
|
||||||
// It ignores the map key, if it does not match.
|
// It ignores the map key, if it does not match.
|
||||||
func Struct(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
func Struct(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||||
var keyToAttributeNameMapping map[string]string
|
return Scan(params, pointer, mapping...)
|
||||||
if len(mapping) > 0 {
|
|
||||||
keyToAttributeNameMapping = mapping[0]
|
|
||||||
}
|
|
||||||
return doStruct(params, pointer, keyToAttributeNameMapping, "")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StructTag acts as Struct but also with support for priority tag feature, which retrieves the
|
// StructTag acts as Struct but also with support for priority tag feature, which retrieves the
|
||||||
@ -405,6 +401,9 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, ma
|
|||||||
|
|
||||||
// Converting by kind.
|
// Converting by kind.
|
||||||
switch kind {
|
switch kind {
|
||||||
|
case reflect.Map:
|
||||||
|
return doMapToMap(value, structFieldValue, mapping)
|
||||||
|
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
// Recursively converting for struct attribute.
|
// Recursively converting for struct attribute.
|
||||||
if err := doStruct(value, structFieldValue, nil, ""); err != nil {
|
if err := doStruct(value, structFieldValue, nil, ""); err != nil {
|
||||||
|
@ -13,12 +13,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Structs converts any slice to given struct slice.
|
// Structs converts any slice to given struct slice.
|
||||||
|
// Also see Scan, Struct.
|
||||||
func Structs(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
func Structs(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||||
var keyToAttributeNameMapping map[string]string
|
return Scan(params, pointer, mapping...)
|
||||||
if len(mapping) > 0 {
|
|
||||||
keyToAttributeNameMapping = mapping[0]
|
|
||||||
}
|
|
||||||
return doStructs(params, pointer, keyToAttributeNameMapping, "")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StructsTag acts as Structs but also with support for priority tag feature, which retrieves the
|
// StructsTag acts as Structs but also with support for priority tag feature, which retrieves the
|
||||||
|
@ -83,7 +83,7 @@ func Test_MapToMap2(t *testing.T) {
|
|||||||
gtest.C(t, func(t *gtest.T) {
|
gtest.C(t, func(t *gtest.T) {
|
||||||
m := make(map[string]User)
|
m := make(map[string]User)
|
||||||
err := gconv.MapToMap(params, &m)
|
err := gconv.MapToMap(params, &m)
|
||||||
t.Assert(err, nil)
|
t.AssertNil(err)
|
||||||
t.Assert(len(m), 1)
|
t.Assert(len(m), 1)
|
||||||
t.Assert(m["key"].Id, 1)
|
t.Assert(m["key"].Id, 1)
|
||||||
t.Assert(m["key"].Name, "john")
|
t.Assert(m["key"].Name, "john")
|
||||||
|
@ -1203,3 +1203,28 @@ func Test_Struct_GVarAttribute(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_Struct_MapAttribute(t *testing.T) {
|
||||||
|
type NodeStatus struct {
|
||||||
|
ID int
|
||||||
|
}
|
||||||
|
type Nodes map[string]NodeStatus
|
||||||
|
type Output struct {
|
||||||
|
Nodes Nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
gtest.C(t, func(t *gtest.T) {
|
||||||
|
var (
|
||||||
|
out = Output{}
|
||||||
|
data = g.Map{
|
||||||
|
"nodes": g.Map{
|
||||||
|
"name": g.Map{
|
||||||
|
"id": 10000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
err := gconv.Struct(data, &out)
|
||||||
|
t.AssertNil(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user