Beego中JSON与XML请求体解析均需手动反序列化,但JSON用json.Unmarshal()、XML用encoding/xml且依赖copyrequestbody=true;两者均要求字段首字母大写并正确配置tag,且路由不自动按Accept头分发。

Beego 中 JSON 与 XML 请求体解析方式不同
Beego 默认不自动解析 RequestBody,无论传的是 JSON 还是 XML,都得手动反序列化。但两者解析路径和依赖条件有明显区别:
- JSON 解析只需标准库
json.Unmarshal(),无额外依赖,结构体字段必须首字母大写(exported),且建议加jsontag 显式控制键名映射 - XML 解析依赖
encoding/xml,同样要求字段 exported,但需用xmltag;若请求体含命名空间、CDATA 或自闭合标签,容易静默失败或字段为空 - Beego 路由不按内容类型自动分发——
/hello/json和/hello/xml是两个独立路由,不能靠Accept头自动切换 handler
copyrequestbody = true 是 XML 解析的隐性前提
Beego 默认会复用 RequestBody 的底层 reader,一旦被中间件或日志读过一次,后续 this.Ctx.Input.RequestBody 就是空字节切片。这对 XML 尤其致命,因为 xml.Unmarshal() 对输入敏感,空输入不报错但字段全零值。
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 必须在
conf/app.conf中显式设置copyrequestbody = true - 该配置影响所有请求体读取,不只是 XML;设为
false时,json.Unmarshal()也可能失败,但因 JSON 错误更易触发 panic 或明确 error,反而更容易暴露问题 - 没开这个开关,
this.Ctx.Input.RequestBody在 controller 里首次读取后就变空,第二次读(比如调试时再打印一遍)就会看到[]
ServeJSON 与 ServeXML 输出行为差异
ServeJSON() 和 ServeXML() 都会设置对应 Content-Type 并序列化 this.Data["json"] 或 this.Data["xml"],但实际输出受运行模式影响:
- 开发模式(
runmode = dev)下,输出带缩进和换行的可读格式;生产模式(runmode = prod)下自动压缩,无空白字符 -
ServeJSON()序列化时会忽略 struct 中未导出字段(小写字母开头),ServeXML()同理,但若字段有xml:"-"tag,也会跳过——这点常被忽略,导致 XML 输出意外缺失字段 - 两者都不校验数据合法性:传
nil指针给ServeJSON()会返回null,传空 struct 给ServeXML()可能生成空标签或直接 omit,行为取决于字段 tag 和零值处理逻辑
Accept 头驱动格式切换需手动实现
Beego 不像 Spring Boot 或 Express 那样内置基于 Accept 头的 content-negotiation。想让同一个 URL(如 /api/user)根据客户端请求头返回 JSON 或 XML,必须自己判断:
- 用
this.Ctx.Input.Header("Accept")获取头值,匹配application/json或application/xml - 不能只看是否包含
json字符串——有些客户端发Accept: */*或Accept: application/vnd.api+json,硬匹配会漏掉 - 更稳妥的做法是用
mime.ParseMediaType()解析,并比较主类型和子类型,再 fallback 到默认格式 - 别在 handler 里混用
this.Data["json"]和this.Data["xml"]——ServeJSON()只读前者,ServeXML()只读后者,写错字段名会导致空白响应
copyrequestbody 开关、Accept 头的手动分发、以及 struct 字段可见性与 tag 的一致性——这三个点没对齐,90% 的解析失败就发生在这里。

















