Browse Source

完成assign tag

yjp 1 year ago
parent
commit
29a68acfce
2 changed files with 82 additions and 12 deletions
  1. 40 0
      examples/assign_tag/main.go
  2. 42 12
      tag/assign_struct.go

+ 40 - 0
examples/assign_tag/main.go

@@ -0,0 +1,40 @@
+package main
+
+import (
+	"fmt"
+	"git.sxidc.com/go-framework/baize/tag"
+)
+
+type JsonBodyID struct {
+	ID string `assign:"toField:Id"`
+}
+
+type UpdateClassJsonBody struct {
+	JsonBodyID
+	Name string `assign:"toField:Name"`
+}
+
+type DomainID struct {
+	Id string
+}
+
+type ClassDomain struct {
+	DomainID
+	Name string
+}
+
+func main() {
+	jsonBody := &UpdateClassJsonBody{
+		JsonBodyID: JsonBodyID{
+			ID: "test_id",
+		},
+		Name: "test",
+	}
+
+	class, err := tag.AssignTo[*ClassDomain](jsonBody)
+	if err != nil {
+		panic(err)
+	}
+
+	fmt.Printf("%+v\n", class)
+}

+ 42 - 12
tag/assign_struct.go

@@ -18,14 +18,18 @@ func AssignTo[T any](from any) (T, error) {
 	}
 
 	fromValue := reflect.ValueOf(from)
-	retValue := reflect.ValueOf(zero)
+	retType := reflect.TypeOf(zero)
+	retValue := reflect.New(retType).Elem()
+	if retValue.Kind() == reflect.Ptr {
+		retValue.Set(reflect.New(retType.Elem()))
+	}
 
 	// 类型校验
 	if fromValue.Kind() != reflect.Ptr && fromValue.Kind() != reflect.Struct {
 		return zero, fserr.New("参数不是结构或结构指针")
 	}
 
-	if fromValue.Kind() == reflect.Ptr && fromValue.Kind() != reflect.Struct {
+	if fromValue.Kind() == reflect.Ptr && fromValue.Elem().Kind() != reflect.Struct {
 		return zero, fserr.New("参数不是结构或结构指针")
 	}
 
@@ -47,11 +51,35 @@ func AssignTo[T any](from any) (T, error) {
 		retElemValue = retValue.Elem()
 	}
 
+	err := assignTo(fromElemValue, &retElemValue)
+	if err != nil {
+		return zero, err
+	}
+
+	return retValue.Interface().(T), nil
+}
+
+func assignTo(fromElemValue reflect.Value, retElemValue *reflect.Value) error {
 	for i := 0; i < fromElemValue.NumField(); i++ {
 		fromField := fromElemValue.Type().Field(i)
-		tag, err := parseAssignTag(fromField)
+		tagStr := fromField.Tag.Get(assignTagKey)
+		if strutils.IsStringEmpty(tagStr) &&
+			(fromField.Type.Kind() == reflect.Struct ||
+				(fromField.Type.Kind() == reflect.Ptr && fromField.Type.Elem().Kind() == reflect.Struct)) {
+			fromStructElemValue := fromElemValue.Field(i)
+			if fromField.Type.Kind() == reflect.Ptr {
+				fromStructElemValue = fromElemValue.Elem()
+			}
+
+			err := assignTo(fromStructElemValue, retElemValue)
+			if err != nil {
+				return err
+			}
+		}
+
+		tag, err := parseAssignTag(fromField, tagStr)
 		if err != nil {
-			return zero, err
+			return err
 		}
 
 		if tag == nil {
@@ -61,7 +89,7 @@ func AssignTo[T any](from any) (T, error) {
 		fromFieldValue := fromElemValue.Field(i)
 
 		// 无效零值,不进行赋值
-		if !fromFieldValue.IsValid() || fromFieldValue.IsNil() || fromFieldValue.IsZero() {
+		if !fromFieldValue.IsValid() || fromFieldValue.IsZero() {
 			continue
 		}
 
@@ -95,16 +123,16 @@ func AssignTo[T any](from any) (T, error) {
 			retFieldElemValue = retFieldValue.Elem()
 		}
 
-		err = assignTo(fromFieldElemValue, retFieldElemValue, tag)
+		err = assignField(fromFieldElemValue, retFieldElemValue, tag)
 		if err != nil {
-			return zero, err
+			return err
 		}
 	}
 
-	return retValue.Interface(), nil
+	return nil
 }
 
-func assignTo(fromFieldElemValue reflect.Value, retFieldElemValue reflect.Value, tag *assignTag) error {
+func assignField(fromFieldElemValue reflect.Value, retFieldElemValue reflect.Value, tag *assignTag) error {
 	fromKind := reflectutils.GroupValueKind(fromFieldElemValue)
 	retKind := reflectutils.GroupValueKind(retFieldElemValue)
 
@@ -117,6 +145,10 @@ func assignTo(fromFieldElemValue reflect.Value, retFieldElemValue reflect.Value,
 			break
 		}
 
+		if retKind == reflect.Struct {
+			return assignTo(fromFieldElemValue, &retFieldElemValue)
+		}
+
 		fromAny = fromFieldElemValue.Interface()
 	case reflect.Slice:
 		if fromFieldElemValue.Elem().Kind() == reflect.String && retKind == reflect.String {
@@ -212,9 +244,7 @@ type assignTag struct {
 	TrimSuffix string
 }
 
-func parseAssignTag(field reflect.StructField) (*assignTag, error) {
-	tagStr := field.Tag.Get(assignTagKey)
-
+func parseAssignTag(field reflect.StructField, tagStr string) (*assignTag, error) {
 	if tagStr == assignIgnore {
 		return nil, nil
 	}