c.JSON 输出细节(HTML 转义、PureJSON)

结论先行

c.JSON 输出 application/json; charset=utf-8,内部走 encoding/json,默认转义 HTML 特殊字符< > & 会变成 \u003c 等)以降低 XSS 风险。想原样输出 <b> 这类内容用 c.PureJSON;想非 ASCII 全部转成 \uXXXXc.AsciiJSON

渲染方法对比

方法行为典型场景
c.JSON(code, obj)encoding/json 默认序列化,转义 HTML 字符普通 API,绝大多数场景
c.PureJSON(code, obj)关闭 HTML 转义,原样输出响应内容含可信 HTML/富文本片段
c.AsciiJSON(code, obj)非 ASCII 转 \uXXXX兼容只认 ASCII 的旧客户端
c.IndentedJSON(code, obj)带缩进的 JSON调试、教学输出
c.JSONP(code, obj)输出 callback 包裹,需防注入跨域 JSONP 老接口(新项目慎用)

使用细节

  • 状态码与 body 一起给:c.JSON(http.StatusOK, obj);第一个参数就是状态码。
  • 一次请求只能成功写一次响应:状态码一旦提交,再调 c.JSON 只是往 body 里追加非法内容(详见第 25 章)。
  • 字段输出受 json tag 控制;time.Time 默认 RFC3339 格式,想改格式就实现 MarshalJSON。
  • gin.H 是 map[string]any 的别名,适合手拼小对象。
  • 序列化失败时(如不可序列化类型),Gin 会打日志但响应已无法回退为错误 JSON。

代码示例

c.JSON(http.StatusOK, gin.H{"msg": "<b>hi</b> & bye"})
// 实际输出: {"msg":"\u003cb\u003ehi\u003c/b\u003e \u0026 bye"}

c.PureJSON(http.StatusOK, gin.H{"msg": "<b>hi</b> & bye"})
// 实际输出: {"msg":"<b>hi</b> & bye"}

c.AsciiJSON(http.StatusOK, gin.H{"msg": "你好"})
// 实际输出: {"msg":"\u4f60\u597d"}

常见追问 / 记忆点

  • 追问:为什么 JSON 要默认转义 HTML?答:历史原因——JSON 常被嵌入 HTML/脚本上下文,转义 < > & 可防止内容被当作标签或破坏结构,属于纵深防御。
  • 追问:PureJSON 与 JSON 性能差别?答:同一套编码器实现,仅是转义开关差异;别为“好看”在生产随意用 PureJSON 输出不可信内容。
  • 记忆点:JSON 转义 HTML、Pure 不转义、Ascii 转非 ASCII;响应只能写一次,状态码先定。
笔记加载中…