Browse Source

JSON 解析和验证器封装

runningwater 7 months ago
parent
commit
213648d7a9

+ 2 - 37
app/http/controllers/api/v1/auth/signup_controller.go

@@ -1,9 +1,6 @@
 package auth
 
 import (
-	"fmt"
-	"net/http"
-
 	"github.com/gin-gonic/gin"
 	v1 "github.com/runningwater/gohub/app/http/controllers/api/v1"
 	"github.com/runningwater/gohub/app/models/user"
@@ -19,23 +16,7 @@ func (controller *SignupController) IsPhoneExist(c *gin.Context) {
 
 	// 初始化请求对象
 	req := requests.SignupPhoneExistRequest{}
-
-	// 解析 JSON 请求
-	if err := c.ShouldBindJSON(&req); err != nil {
-		c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{
-			"error": "请求参数错误"+ err.Error(),
-		})
-		// 打印错误信息
-		fmt.Println(err.Error())
-		return
-	}
-
-	// 表单验证
-	errs := requests.ValidateSignupPhoneExist(&req, c)
-	if len(errs) > 0 {
-		c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{
-			"errors": errs,
-		})
+	if ok := requests.Validate(c, &req, requests.ValidateSignupPhoneExist); !ok {
 		return
 	}
 
@@ -50,23 +31,7 @@ func (controller *SignupController) IsEmailExist(c *gin.Context) {
 
 	// 初始化请求对象
 	req := requests.SignupEmailExistRequest{}
-
-	// 解析 JSON 请求
-	if err := c.ShouldBindJSON(&req); err != nil {
-		c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{
-			"error": "请求参数错误"+ err.Error(),
-		})
-		// 打印错误信息
-		fmt.Println(err.Error())
-		return
-	}
-
-	// 表单验证
-	errs := requests.ValidateSignupEmailExist(&req, c)
-	if len(errs) > 0 {
-		c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{
-			"errors": errs,
-		})
+	if ok := requests.Validate(c, &req, requests.ValidateSignupEmailExist);!ok {
 		return
 	}
 

+ 68 - 0
app/requests/requests.go

@@ -0,0 +1,68 @@
+// Package requests 处理请求数据和表单验证逻辑
+package requests
+
+import (
+	"net/http"
+
+	"github.com/gin-gonic/gin"
+	"github.com/thedevsaddam/govalidator"
+)
+
+// ValidatorFunc 定义验证函数类型
+// 该函数接受一个数据和一个上下文参数,并返回一个包含错误信息的映射
+type ValidatorFunc func(any, *gin.Context) map[string][]string
+
+// Validate 函数用于验证请求数据
+// 它接受一个上下文对象、要验证的数据和一个验证函数
+// 如果验证成功,返回 true;否则返回 false,并在上下文中设置错误响应
+// c: gin.Context 上下文对象
+// obj: 需要验证的数据对象
+// handler: 自定义验证函数
+// 返回值是一个布尔值,表示验证是否成功  如果验证失败,返回错误信息,否则返回空映射
+// 调用示例:
+// if ok := requests.Validate(c, &requests.SignupRequest{}, requests.Signup); !ok {
+//       return
+// }
+func Validate(c *gin.Context, obj any, handler ValidatorFunc) bool {
+
+	// 1. 解析请求, 支持 JSON 数据、表单请求和 URL Query 参数
+	if err := c.ShouldBind(obj); err != nil {
+		c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{
+			"message": "请求解析错误,请确认请求格式是否正确。上传文件请使用 multipart 标头, 参数请使用 JSON 格式",
+			"error": err.Error(),
+		})
+		return false
+	}
+
+	// 2. 执行验证
+	errs := handler(obj, c)
+
+	// 3. 如果验证失败,返回错误信息
+	if len(errs) > 0 {
+		c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{
+			"message": "请求验证不通过,具体请查看 errors",
+			"errors": errs,
+		})
+		return false
+	}
+	// 4. 返回验证成功
+	return true
+}
+
+// validate 函数用于执行数据验证
+// 它接受数据、验证规则和自定义错误信息,并返回验证结果
+// data: 需要验证的数据
+// rules: 验证规则
+// messages: 自定义错误信息
+// 返回值是一个映射,包含字段名和对应的错误信息
+func validate(data any, rules, messages govalidator.MapData) map[string][]string {
+	
+	opts := govalidator.Options{
+		Data:         data,
+		Rules:        rules,
+		TagIdentifier: "valid", // 使用结构体中的valid标签
+		Messages:     messages,
+	}	
+
+	return govalidator.New(opts).ValidateStruct()
+}

+ 2 - 17
app/requests/signup_request.go

@@ -28,15 +28,8 @@ func ValidateSignupPhoneExist(data any, c *gin.Context) map[string][]string {
 			},
 		}
 
-		opts := govalidator.Options{
-			Data:         data,
-			Rules: 	 rules,
-			TagIdentifier: "valid", // 使用结构体中的valid标签
-			Messages:     messages,
-		}
-
 		// 执行验证
-		return govalidator.New(opts).ValidateStruct()
+		return validate(data, rules, messages)
 }
 
 
@@ -56,14 +49,6 @@ func ValidateSignupEmailExist(data any, c *gin.Context) map[string][]string {
 			"email:Email 格式不正确,请提供有效的邮箱地址",
 		},
 	}
-
-	opts := govalidator.Options{
-		Data:         data,
-		Rules: 	 rules,
-		TagIdentifier: "valid", // 使用结构体中的valid标签
-		Messages:     messages,
-	}
-
 	// 执行验证
-	return govalidator.New(opts).ValidateStruct()
+	return validate(data, rules, messages)
 }

+ 1 - 1
gohub.http

@@ -3,7 +3,7 @@ POST {{base_url}}/v1/auth/signup/phone/exist HTTP/1.1
 Content-Type: application/json
 
 {
-  "phone": "13661164483"
+  "phone": "15968875425"
 }
 
 ### POST /signup/email/exist 注册邮箱是否已存在