88 lines
1.6 KiB
Go
88 lines
1.6 KiB
Go
package actions
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
func findByTag(obj any, tag string) (int, error) {
|
|
structType := reflect.TypeOf(obj).Elem()
|
|
for i := 0; i < structType.NumField(); i++ {
|
|
fieldTags := structType.Field(i).Tag.Get("json")
|
|
if tag == strings.Split(fieldTags, ",")[0] {
|
|
return i, nil
|
|
}
|
|
}
|
|
return -1, fmt.Errorf("No such field: %s in obj", tag)
|
|
}
|
|
|
|
func setField(obj any, name string, value any) error {
|
|
structValue := reflect.ValueOf(obj).Elem()
|
|
idx, err := findByTag(obj, name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
structFieldValue := structValue.Field(idx)
|
|
|
|
if !structFieldValue.IsValid() {
|
|
return fmt.Errorf("No such field: %s in obj", name)
|
|
}
|
|
|
|
if !structFieldValue.CanSet() {
|
|
return fmt.Errorf("Cannot set %s field value", name)
|
|
}
|
|
|
|
structFieldType := structFieldValue.Type()
|
|
val := reflect.ValueOf(value)
|
|
if structFieldType != val.Type() {
|
|
return ErrObjTypeNotMatch
|
|
}
|
|
|
|
if value == nil {
|
|
structFieldValue.Set(reflect.Zero(structFieldType))
|
|
} else {
|
|
structFieldValue.Set(val)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func isPointer(obj any) bool {
|
|
iv := reflect.ValueOf(obj)
|
|
if !iv.IsValid() {
|
|
return false
|
|
}
|
|
|
|
return iv.Kind() == reflect.Pointer
|
|
}
|
|
|
|
func FillStruct(m map[string]any, obj any) error {
|
|
if !isPointer(obj) {
|
|
return ErrObjNotPointer
|
|
}
|
|
|
|
for k, v := range m {
|
|
if v == nil {
|
|
continue
|
|
}
|
|
|
|
err := setField(obj, k, v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func Dereference(input any) any {
|
|
v := reflect.ValueOf(input)
|
|
|
|
// Check if the value is a pointer
|
|
if v.Kind() == reflect.Pointer {
|
|
// v.Elem() returns the value the pointer points to
|
|
return v.Elem().Interface()
|
|
}
|
|
|
|
return input
|
|
}
|