Golang Web接口返回JSON乱码怎么办_JSON编码问题说明

11次阅读

根本原因是响应头缺失Content-Type的charset声明,go默认输出UTF-8字节但客户端未获知编码;需显式设置Header(“Content-Type”, “application/json; charset=utf-8”),并确保源文件、中间件、代理均不破坏该声明。

Golang Web接口返回JSON乱码怎么办_JSON编码问题说明

Go http 返回 json 时中文显示为 或乱码

根本原因不是 Go 本身编码错误,而是响应头缺失 Content-Type 的字符集声明。Go 的 json.Marshal 默认输出 UTF-8 字节,但浏览器或客户端若没收到 Content-Type: application/json; charset=utf-8,可能按 ISO-8859-1 或系统默认编码解析,导致中文变问号或乱码。

  • 务必在写响应前显式设置响应头:w.Header().Set("Content-Type", "application/json; charset=utf-8")
  • 不要依赖框架自动添加 charset(如 net/http 原生不加,gin 默认加但某些中间件可能覆盖)
  • curl -v浏览器开发者工具 Network 面板确认响应头中 Content-Type 是否含 charset=utf-8

使用 json.MarshalIndent 导致响应体开头多出空格或换行

开发调试时常用 json.MarshalIndent 格式化输出,但它会在 JSON 前插入缩进和换行(比如 n {),而 HTTP 响应体开头若出现空白字符,部分严格解析的客户端(如某些嵌入式 HTTP 库、postman 的某些模式)会直接报解析失败或丢弃首字符,表现为乱码或无效 JSON。

  • 生产环境禁用 json.MarshalIndent,只在日志或调试接口中使用
  • 若必须格式化响应,确保不破坏响应流:先 json.Marshal 得到字节切片,再用 json.Indent 处理,最后整体写入 w.Write
  • 注意 http.ResponseWriter 一旦调用 WriteHeader 或首次 Write,响应头即锁定,不能再改 Content-Type
data := map[String]interface{}{"msg": "你好"} b, _ := json.Marshal(data) var out bytes.Buffer json.Indent(&out, b, "", "  ") w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Write(out.Bytes())

Gin 框架中 c.JSON() 仍乱码的排查点

c.JSON(200, data) 内部已设置 Content-Type: application/json; charset=utf-8,但仍有乱码,大概率是中间件或自定义逻辑干扰了响应头。

  • 检查是否在 c.JSON() 前调用了 c.Header("Content-Type", ...)c.Data() 等底层写入方法
  • 确认没有全局注册的响应拦截中间件(如日志中间件)误写了响应头
  • 若用了 c.Render() 自定义模板,需手动设置 charset;c.JSON() 不走该流程
  • Gin v1.9+ 对非 ASCII 字符更严格,若结构体字段 tag 含 json:"name,string" 且值为非 UTF-8 字节,也会触发编码异常

前端 fetch 或 axios 接收 JSON 后仍显示乱码

服务端已正确返回 UTF-8 JSON 和响应头,但 JS 中 response.json() 解析后中文仍是乱码,问题通常出在传输层或前端解析时机。

立即学习go语言免费学习笔记(深入)”;

  • 确认响应状态码是 200,且未被代理(如 nginx)截断或转码:Nginx 默认不修改响应体,但若配置了 charset utf-8;location 块中,可能强制重写响应头,反而冲突
  • 避免在 fetch 中手动调用 response.text()JSON.parse() —— 这绕过了浏览器内置的 charset 检测逻辑,应直接用 response.json()
  • chrome 开发者工具中查看 Response Headers,确认 Content-Type 未被覆盖;Response Preview 若显示乱码但 Raw 显示正常,说明是前端渲染问题而非传输问题

最易忽略的是:本地测试时用 go run main.go 启动,但文件本身保存为 GBK 编码(尤其 windows 记事本),导致源码里中文字符串字面量就是 GBK 字节,json.Marshal 只是原样编码输出,结果服务端发的是 GBK 字节流却声明了 UTF-8 charset —— 浏览器照着 UTF-8 解,必然乱码。务必统一用 UTF-8 编码保存 Go 源文件。

text=ZqhQzanResources