Beego中接收JSON答卷需手动解码:先校验Content-Type为application/json,再用json.Unmarshal解析RequestBody到带json标签的导出结构体,禁用ParseForm;阅卷逻辑须按题型差异化处理,单选题去空格严格比对,多选题统一排序后逐项比对或reflect.DeepEqual;调用Python脚本需设超时、分离stdout/stderr、验证输出JSON合法性;数据库写入应使用ReadOrCreate或事务确保幂等性。

Beego 中如何用 Controller 接收并解析考生提交的 JSON 答卷
Beego 默认不自动解析请求体中的 JSON,直接调用 this.Ctx.Input.RequestBody 拿到的是原始字节,容易误判为空或乱码。必须手动解码,且要注意 Content-Type 校验和结构体字段标签。
- 确保前端请求头包含
Content-Type: application/json,否则 Beego 可能跳过解析逻辑 - 定义答卷结构体时,所有需绑定的字段必须导出(首字母大写),并显式加上
json:"xxx"标签,比如Answer string `json:"answer"` - 不要依赖
this.ParseForm()——它只处理application/x-www-form-urlencoded,对 JSON 无效 - 推荐写法:
var submit struct { QuestionID int `json:"question_id"` Answer string `json:"answer"` } err := json.Unmarshal(this.Ctx.Input.RequestBody, &submit) if err != nil { this.Data["json"] = map[string]interface{}{"error": "invalid json"} this.ServeJSON() return }
判断单选题/多选题答案是否正确的核心逻辑怎么写
阅卷不是简单字符串相等,要区分题型、忽略空格、大小写、顺序(尤其多选题),还要兼容后台预设答案的多种存储格式(如逗号分隔字符串、JSON 数组)。
- 单选题:用
strings.TrimSpace()清理考生答案后,与标准答案(也需去空格)严格比对 - 多选题:标准答案若存为
"A,C,D",先用strings.Split()拆成切片,再用sort.Strings()排序;考生答案同样处理,最后用reflect.DeepEqual()或逐项比对 - 避免直接用
==比较两个切片——Go 中切片不能直接比较,会编译报错invalid operation: == (mismatched types []string and []string) - 如果标准答案存在数据库中是 JSON 字符串(如
["A","C","D"]),务必先json.Unmarshal成[]string,别当成普通字符串去 split
Beego 里怎么安全调用外部 Python 阅卷脚本(比如需要 NLP 批改简答题)
直接用 exec.Command 调 Python 容易阻塞 HTTP 请求、超时、路径错误或权限问题,且 stdout/stderr 混淆会导致解析失败。
- Python 脚本入口必须接受标准输入(
sys.stdin)接收 JSON 答卷,输出也必须是合法 JSON 到 stdout,末尾不带多余换行或提示文字 - Go 侧调用时设置超时:
cmd := exec.Command("python3", "/path/to/grade.py") cmd.Stdin = strings.NewReader(inputJSON) var outBuf, errBuf bytes.Buffer cmd.Stdout, cmd.Stderr = &outBuf, &errBuf cmd.WaitTimeout = 5 * time.Second // Beego 2.x 支持,旧版需用 context.WithTimeout - 执行后必须同时检查
err(命令启动失败)、errBuf.String()(Python 报错)、outBuf.String()(是否为合法 JSON),三者缺一不可 - 不要把 Python 脚本放在
static/目录下——Beego 会当作静态文件暴露,有安全风险
阅卷结果写入 MySQL 时,为什么 Insert 总是丢数据或主键冲突
常见原因是没处理事务、忽略自增主键返回值、或并发提交时未加锁,导致同一考生多次提交覆盖成绩,或阅卷结果与试卷 ID 关联错位。
- 用
orm.ReadOrCreate()替代裸Insert,避免重复插入相同exam_id + user_id组合 - 阅卷完成后必须用
o.Read(&record, "Id")或o.Insert()返回的int64主键,再更新关联表(如题目得分明细),不能靠前端传来的 ID - 如果支持“重阅”,需在 SQL 层加
ON DUPLICATE KEY UPDATE,对应 Beego ORM 的o.QueryTable("score").Filter("user_id", uid).Filter("exam_id", eid).Update(...) - 注意 MySQL 的
autocommit默认开启,但 Beego ORM 在Begin()后必须显式Commit()或Rollback(),否则事务挂起,连接池耗尽
阅卷模块最脆弱的环节不在算法,而在 JSON 解析边界、Python 子进程生命周期控制、以及数据库写入的幂等性设计——这三处出问题,轻则返回空结果,重则污染生产数据。


















