Golang+Gin+Gorm提交嵌套JSON创建记录仅loggedUser字段生效问题
问题排查与解决方案
问题1:JSON反序列化字段不匹配
- 前端提交的雇员明细字段为
employee_detail,但你的Emp结构体中EmpDetail字段的json标签为emp_detail,名称不匹配导致反序列化时无法读取到对应数据 - 明细结构体内部字段json标签也和前端提交字段不匹配:前端提交
emp_id、emp_date,但你的结构体标签写的是Emp_id、date,对应不上导致子字段全部为空
问题2:Gorm关联配置错误
- 你在
EmpDetail切片上标注了foreignKey:TripId,但匿名的明细结构体中根本没有定义TripId字段,外键不存在导致关联关系失效 - Gorm默认不会自动保存关联的子切片数据,需要额外开启关联保存配置
问题3:匿名明细结构体不规范
内嵌的匿名明细结构体Gorm无法正常识别关联关系,需要单独定义为公开结构体
修改方案
1. 修正Model定义
type Base struct { gorm.Model ID string `gorm:"primary_key;not_null" json:"id"` } // 单独定义EmpDetail结构体 type EmpDetail struct { gorm.Model TripId string `gorm:"not_null"` // 关联Emp主表的外键 EmpId string `gorm:"not_null;" json:"emp_id"` // 修正json标签匹配前端字段 Date string `gorm:"size:255;not_null;" json:"emp_date"` // 修正json标签匹配前端emp_date FromAddress string `gorm:"size:255;not_null;" json:"from_address"` ToAddress string `gorm:"size:255;not_null;" json:"to_address"` Reason string `gorm:"size:255;not_null;" json:"reason"` Comments string `gorm:"size:255;not_null;" json:"comments"` } type Emp struct { Base LoggedUser LoggedUser `gorm:"embedded" json:"logged_user"` // 修正json标签匹配前端employee_detail,补充正确的关联配置 EmpDetail []EmpDetail `gorm:"foreignKey:TripId;references:ID" json:"employee_detail"` }
2. 修正SaveEmp方法,开启关联保存
func (emp *Emp) SaveEmp(db *gorm.DB) (*Emp, error) { // 开启FullSaveAssociations自动保存关联子数据 if err := db.Debug().Session(&gorm.Session{FullSaveAssociations: true}).Create(&emp).Error; err != nil { return &Emp{}, err } return emp, nil }
3. 可选优化Controller代码
不需要手动读取请求体反序列化,直接使用Gin提供的绑定方法更简洁:
func (server *Server) CreateEmp(context *gin.Context) { errMessage := map[string]string{} var emp models.Emp // 直接绑定JSON,替代手动读body+Unmarshal if err := context.ShouldBindJSON(&emp); err != nil { errMessage["参数解析失败"] = err.Error() context.JSON(http.StatusUnprocessableEntity, gin.H{ "status": http.StatusUnprocessableEntity, "error": errMessage, }) return } createdEmp, err := emp.SaveEmp(server.DB) if err != nil { context.JSON(http.StatusInternalServerError, gin.H{ "status": http.StatusInternalServerError, "error": err.Error(), }) return } context.JSON(http.StatusOK, gin.H{ "status": http.StatusOK, "response": createdEmp, }) }
修改完成后先在反序列化后打印emp.EmpDetail确认字段已经正确解析,再验证数据库写入即可。
内容的提问来源于stack exchange,提问作者Raj
相关产品推荐
相关产品推荐

