mirror of
https://gitee.com/johng/gf.git
synced 2024-12-02 04:07:47 +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
|
||||
}
|
||||
// Automatically mapping and filtering the struct attribute.
|
||||
// TODO struct fields in sequence
|
||||
data := DataToMapDeep(in.Where)
|
||||
if in.Table != "" {
|
||||
data, _ = db.GetCore().mappingAndFilterData(in.Schema, in.Table, data, true)
|
||||
|
@ -273,7 +273,7 @@ func (g *RouterGroup) getPrefix() string {
|
||||
return prefix
|
||||
}
|
||||
|
||||
// doBindRoutersToServer does really registering for the group.
|
||||
// doBindRoutersToServer does really register for the group.
|
||||
func (g *RouterGroup) doBindRoutersToServer(item *preBindItem) *RouterGroup {
|
||||
var (
|
||||
bindType = item.bindType
|
||||
@ -289,7 +289,7 @@ func (g *RouterGroup) doBindRoutersToServer(item *preBindItem) *RouterGroup {
|
||||
if err != nil {
|
||||
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 {
|
||||
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.
|
||||
// It cannot start running when added to gtimer.
|
||||
// It should start running after the entry is added to the entries map,
|
||||
// to avoid the task from running during adding where the entries
|
||||
// does not have the entry information, which might cause panic.
|
||||
// It should start running after the entry is added to the Cron entries map, to avoid the task
|
||||
// from running during adding where the entries do not have the entry information, which might cause panic.
|
||||
entry.entry = gtimer.AddEntry(time.Second, entry.check, singleton, -1, gtimer.StatusStopped)
|
||||
c.entries.Set(entry.Name, entry)
|
||||
entry.entry.Start()
|
||||
@ -70,7 +69,7 @@ func (entry *Entry) IsSingleton() bool {
|
||||
|
||||
// SetSingleton sets the entry running in singleton mode.
|
||||
func (entry *Entry) SetSingleton(enabled bool) {
|
||||
entry.entry.SetSingleton(true)
|
||||
entry.entry.SetSingleton(enabled)
|
||||
}
|
||||
|
||||
// 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`.
|
||||
//
|
||||
// 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:
|
||||
// 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
|
||||
// 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 (
|
||||
paramsRv reflect.Value
|
||||
paramsKind reflect.Kind
|
||||
paramsRv reflect.Value
|
||||
paramsKind reflect.Kind
|
||||
keyToAttributeNameMapping map[string]string
|
||||
)
|
||||
if len(mapping) > 0 {
|
||||
keyToAttributeNameMapping = mapping[0]
|
||||
}
|
||||
if v, ok := params.(reflect.Value); ok {
|
||||
paramsRv = v
|
||||
} else {
|
||||
@ -113,7 +117,7 @@ func doMapToMap(params interface{}, pointer interface{}, mapping ...map[string]s
|
||||
e := reflect.New(pointerValueType).Elem()
|
||||
switch pointerValueKind {
|
||||
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
|
||||
}
|
||||
default:
|
||||
|
@ -11,28 +11,41 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Scan automatically calls MapToMap, MapToMaps, Struct or Structs function according to
|
||||
// the type of parameter `pointer` to implement the converting.
|
||||
// Scan automatically checks the type of `pointer` and converts `params` to `pointer`. It supports `pointer`
|
||||
// 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 MapToMaps if `pointer` is type of *[]map/*[]*map to do the converting.
|
||||
// It calls function Struct if `pointer` is type of *struct/**struct to do the converting.
|
||||
// It calls function Structs if `pointer` is type of *[]struct/*[]*struct to do the converting.
|
||||
// It calls function `doMapToMap` internally if `pointer` is type of *map for converting.
|
||||
// It calls function `doMapToMaps` internally if `pointer` is type of *[]map/*[]*map for converting.
|
||||
// It calls function `doStruct` internally if `pointer` is type of *struct/**struct for 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) {
|
||||
var (
|
||||
pointerType = reflect.TypeOf(pointer)
|
||||
pointerKind = pointerType.Kind()
|
||||
pointerType reflect.Type
|
||||
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 {
|
||||
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 (
|
||||
pointerElem = pointerType.Elem()
|
||||
pointerElemKind = pointerElem.Kind()
|
||||
pointerElem = pointerType.Elem()
|
||||
pointerElemKind = pointerElem.Kind()
|
||||
keyToAttributeNameMapping map[string]string
|
||||
)
|
||||
if len(mapping) > 0 {
|
||||
keyToAttributeNameMapping = mapping[0]
|
||||
}
|
||||
switch pointerElemKind {
|
||||
case reflect.Map:
|
||||
return MapToMap(params, pointer, mapping...)
|
||||
return doMapToMap(params, pointer, mapping...)
|
||||
|
||||
case reflect.Array, reflect.Slice:
|
||||
var (
|
||||
@ -44,11 +57,13 @@ func Scan(params interface{}, pointer interface{}, mapping ...map[string]string)
|
||||
sliceElemKind = sliceElem.Kind()
|
||||
}
|
||||
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:
|
||||
return Struct(params, pointer, mapping...)
|
||||
|
||||
return doStruct(params, pointer, keyToAttributeNameMapping, "")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,11 +31,7 @@ import (
|
||||
// in mapping procedure to do the matching.
|
||||
// It ignores the map key, if it does not match.
|
||||
func Struct(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
var keyToAttributeNameMapping map[string]string
|
||||
if len(mapping) > 0 {
|
||||
keyToAttributeNameMapping = mapping[0]
|
||||
}
|
||||
return doStruct(params, pointer, keyToAttributeNameMapping, "")
|
||||
return Scan(params, pointer, mapping...)
|
||||
}
|
||||
|
||||
// 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.
|
||||
switch kind {
|
||||
case reflect.Map:
|
||||
return doMapToMap(value, structFieldValue, mapping)
|
||||
|
||||
case reflect.Struct:
|
||||
// Recursively converting for struct attribute.
|
||||
if err := doStruct(value, structFieldValue, nil, ""); err != nil {
|
||||
|
@ -13,12 +13,9 @@ import (
|
||||
)
|
||||
|
||||
// Structs converts any slice to given struct slice.
|
||||
// Also see Scan, Struct.
|
||||
func Structs(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
var keyToAttributeNameMapping map[string]string
|
||||
if len(mapping) > 0 {
|
||||
keyToAttributeNameMapping = mapping[0]
|
||||
}
|
||||
return doStructs(params, pointer, keyToAttributeNameMapping, "")
|
||||
return Scan(params, pointer, mapping...)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
m := make(map[string]User)
|
||||
err := gconv.MapToMap(params, &m)
|
||||
t.Assert(err, nil)
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(m), 1)
|
||||
t.Assert(m["key"].Id, 1)
|
||||
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