Gin框架BindJSON绑定[]byte字段报错,如何无需改类型解决?
解决Gin BindJSON绑定[]byte类型Password字段的报错问题
核心原因
Gin默认处理JSON到[]byte字段的绑定时,会尝试对字符串做Base64解码,而普通密码字符串并非Base64格式,因此触发解码错误。
方案一:自定义Password类型实现JSON编解码接口(推荐)
给模型的Password字段定义自定义类型,实现json.Unmarshaler和json.Marshaler接口,让Gin直接将字符串转为[]byte,同时保证序列化输出时是正常字符串:
import ( "encoding/json" "strings" "gorm.io/gorm" ) // 自定义Password类型,底层为[]byte type Password []byte // 实现UnmarshalJSON,直接将JSON字符串转为[]byte func (p *Password) UnmarshalJSON(data []byte) error { // 去除JSON字符串的前后引号 rawStr := strings.Trim(string(data), "\"") *p = Password(rawStr) return nil } // 实现MarshalJSON,将[]byte转为JSON字符串(避免返回Base64格式) func (p Password) MarshalJSON() ([]byte, error) { return json.Marshal(string(p)) } // 你的GORM模型 type User struct { gorm.Model Username string `json:"username"` Password Password `json:"password"` // 使用自定义类型 }
使用c.BindJSON(&user)绑定请求体时,会自动调用自定义解码逻辑,不会触发Base64解码错误;同时GORM可正常将Password类型作为[]byte存储到数据库(底层类型一致)。
方案二:手动解析请求体后赋值
如果不想修改模型字段类型,可手动解析JSON请求体,再将密码字符串转为[]byte赋值给模型:
import ( "net/http" "github.com/gin-gonic/gin" ) func CreateUser(c *gin.Context) { // 先解析到临时map var req map[string]interface{} if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // 校验字段存在性后赋值 username, ok := req["username"].(string) if !ok { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid username"}) return } passwordStr, ok := req["password"].(string) if !ok { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid password"}) return } user := &User{ Username: username, Password: []byte(passwordStr), } // 后续执行GORM操作,如保存 // db.Create(user) c.JSON(http.StatusOK, gin.H{"msg": "success"}) }
这种方式需额外做字段存在性和类型校验,避免类型断言panic。
内容的提问来源于stack exchange,提问作者yogopo
相关产品推荐
相关产品推荐

