You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 15:27:03