c.json不是唯一选择,因它默认html转义可能破坏富文本等场景;c.purejson跳过转义,c.indentedjson仅限调试,c.securejson仅对顶层数组加防护,且所有方法均要求字段导出并配json tag。

c.JSON 是 Gin 默认且最常用的 JSON 响应方法,但它不是唯一选择——Gin 确实支持多种响应序列化器,每种对应不同场景和约束。
为什么不能只用 c.JSON?
c.JSON 对结构体字段做 HTML 字符转义(如 → <code>\u003c),这是为防 XSS 设计的默认行为。但如果你返回的是前端要直接执行的 JS 代码、富文本内容、或已由前端框架处理转义的字符串,这种转义反而会破坏原始值。
常见现象:返回 {"content":"<div>hello</div>"},实际得到 {"content":"\u003cdiv\u003ehello\u003c/div\u003e"}。
这时你需要 c.PureJSON:它跳过 HTML 转义,原样输出 Unicode 字符。
c.IndentedJSON 只适合开发环境
c.IndentedJSON 生成带缩进和换行的 JSON,可读性高,但有明确性能代价:
- CPU 开销比 c.JSON 高约 2–3 倍(因格式化逻辑)
- 响应体积增大 15%–25%(空格/换行)
- 不符合 HTTP 缓存友好原则(空白字符影响 ETag 计算)
生产环境务必避免;仅在调试接口、写文档示例或本地测试时使用。
替代方案:用浏览器 DevTools 或 jq 格式化响应,不依赖服务端。
c.SecureJSON 的数组防护机制容易被忽略
c.SecureJSON 专为防止 JSON 劫持(JSON Hijacking)设计,对顶层数组自动前置 while(1);。
但它的触发条件很具体:
- 仅当 obj 类型是切片([]T)或数组([N]T)时才加前缀
- 若传入 gin.H{"data": []User{...}}(即 map 包裹数组),**不会加前缀**
- 它不校验内容是否真为敏感数据,也不提供开关选项
如果你用它只为“看起来更安全”,而实际没暴露用户私有数组接口,那它只是徒增客户端解析负担。
选错序列化器可能暴露字段或破坏兼容性
Go 结构体字段必须首字母大写(导出)+ 显式json tag 才能被 c.JSON 等方法序列化。
但不同方法对 tag 的依赖程度不同:
- c.JSON、c.PureJSON、c.IndentedJSON 行为一致,都严格依赖导出性和 tag
- c.AsciiJSON 会强制把 Unicode 转成 \uXXXX 形式,但不解决字段不可见问题
- c.XML 或 c.YAML 则各自走独立序列化逻辑,json tag 完全无效,需用 xml 或 yaml tag
最容易被忽略的点:同一个结构体混用多种响应格式时,必须同时维护多套 tag,否则某类响应会丢失字段。











