|
|
|
@@ -25,6 +25,48 @@ type StructField struct {
|
|
|
|
|
Field reflect.StructField
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// StructFieldNameByTag get struct field name by tag key and its value
|
|
|
|
|
func StructFieldNameByTag(src interface{}, tkey string, tval string) (string, interface{}, error) {
|
|
|
|
|
sv := reflect.ValueOf(src)
|
|
|
|
|
if sv.Kind() == reflect.Ptr {
|
|
|
|
|
sv = sv.Elem()
|
|
|
|
|
}
|
|
|
|
|
if sv.Kind() != reflect.Struct {
|
|
|
|
|
return "", nil, ErrInvalidStruct
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typ := sv.Type()
|
|
|
|
|
for idx := 0; idx < typ.NumField(); idx++ {
|
|
|
|
|
fld := typ.Field(idx)
|
|
|
|
|
val := sv.Field(idx)
|
|
|
|
|
if len(fld.PkgPath) != 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ts, ok := fld.Tag.Lookup(tkey); ok {
|
|
|
|
|
for _, p := range strings.Split(ts, ",") {
|
|
|
|
|
if p == tval {
|
|
|
|
|
return fld.Name, val.Interface(), nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch val.Kind() {
|
|
|
|
|
case reflect.Ptr:
|
|
|
|
|
if val = val.Elem(); val.Kind() == reflect.Struct {
|
|
|
|
|
if name, fld, err := StructFieldNameByTag(val.Interface(), tkey, tval); err == nil {
|
|
|
|
|
return name, fld, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case reflect.Struct:
|
|
|
|
|
if name, fld, err := StructFieldNameByTag(val.Interface(), tkey, tval); err == nil {
|
|
|
|
|
return name, fld, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return "", nil, ErrNotFound
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// StructFieldByTag get struct field by tag key and its value
|
|
|
|
|
func StructFieldByTag(src interface{}, tkey string, tval string) (interface{}, error) {
|
|
|
|
|
sv := reflect.ValueOf(src)
|
|
|
|
@@ -46,9 +88,6 @@ func StructFieldByTag(src interface{}, tkey string, tval string) (interface{}, e
|
|
|
|
|
if ts, ok := fld.Tag.Lookup(tkey); ok {
|
|
|
|
|
for _, p := range strings.Split(ts, ",") {
|
|
|
|
|
if p == tval {
|
|
|
|
|
if val.Kind() != reflect.Ptr && val.CanAddr() {
|
|
|
|
|
val = val.Addr()
|
|
|
|
|
}
|
|
|
|
|
return val.Interface(), nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -72,10 +111,21 @@ func StructFieldByTag(src interface{}, tkey string, tval string) (interface{}, e
|
|
|
|
|
|
|
|
|
|
// ZeroFieldByPath clean struct field by its path
|
|
|
|
|
func ZeroFieldByPath(src interface{}, path string) error {
|
|
|
|
|
if src == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
var err error
|
|
|
|
|
val := reflect.ValueOf(src)
|
|
|
|
|
|
|
|
|
|
if IsEmpty(val) {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, p := range strings.Split(path, ".") {
|
|
|
|
|
if IsEmpty(val) {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val, err = structValueByName(val, p)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
@@ -493,13 +543,14 @@ func btSplitter(str string) []string {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// queryToMap turns something like a[b][c]=4 into
|
|
|
|
|
// map[string]interface{}{
|
|
|
|
|
// "a": map[string]interface{}{
|
|
|
|
|
// "b": map[string]interface{}{
|
|
|
|
|
// "c": 4,
|
|
|
|
|
// },
|
|
|
|
|
// },
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// map[string]interface{}{
|
|
|
|
|
// "a": map[string]interface{}{
|
|
|
|
|
// "b": map[string]interface{}{
|
|
|
|
|
// "c": 4,
|
|
|
|
|
// },
|
|
|
|
|
// },
|
|
|
|
|
// }
|
|
|
|
|
func queryToMap(param string) (map[string]interface{}, error) {
|
|
|
|
|
rawKey, rawValue, err := splitKeyAndValue(param)
|
|
|
|
|
if err != nil {
|
|
|
|
|