json.Unmarshal 报错“invalid character”主因是字符串非标准JSON格式,如单引号、尾逗号、大小写布尔值;其次常因结构体字段未导出(小写首字母)导致静默失败;解析动态JSON应优先用map[string]interface{}或json.RawMessage;中文乱码需用json.Encoder.SetEscapeHTML(false)解决。

为什么 json.Unmarshal 报错 “invalid character”?
多数情况下不是字符串本身有问题,而是传入的字符串不是合法 JSON 格式——比如用了单引号、尾部多逗号、或混了 Go 字面量(如 true 写成 True)。json.Unmarshal 只认标准 JSON,不兼容 JavaScript 或 Go 的宽松语法。
- 检查字符串是否以
"包裹 key 和 string 值,不能用' - 确保布尔值是小写:
true/false,不是True或1 - 如果字符串来自前端或日志,先用
strings.TrimSpace去掉首尾空格和 BOM - 调试时可先用
json.Valid([]byte(s))判断是否合法,避免直接 panic
结构体字段必须导出才能被 json.Unmarshal 解析
Go 的 json 包只处理导出字段(首字母大写),小写字段会被忽略,且不报错。这是最常被忽略的“静默失败”原因。
- 字段名必须大写,例如
Name而非name - 用 struct tag 显式指定 key:例如
Name string `json:"name"` - 如果字段可能为空,建议加
omitempty,但注意它只影响序列化(json.Marshal),不影响反序列化 - 嵌套结构体也要满足导出规则,否则整层丢失
如何安全地解析未知结构的 JSON 字符串?
当不知道 JSON 结构、或字段动态变化时,别硬塞进固定 struct,优先用 map[string]interface{} 或 json.RawMessage。
-
map[string]interface{}适合简单扁平结构,但数值默认是float64,取int或string需类型断言 - 深层嵌套或混合类型时,用
json.RawMessage延迟解析:声明字段为Data json.RawMessage,后续按需再json.Unmarshal - 避免用
interface{}直接接收,它会把数字全转成float64,整型精度可能丢失(尤其 ID 类字段) - 如果字段名含特殊字符(如
"user-id"),struct tag 必须写成json:"user-id",不能靠命名自动映射
json.Marshal 输出中文乱码?
默认会把中文转成 Unicode 转义(\u4f60\u597d),这不是 bug,是 JSON 标准允许的行为。需要可读中文,得显式禁用转义。
立即学习“go语言免费学习笔记(深入)”;
- 用
json.MarshalIndent时同样会出现,解决方式一致 - 正确做法:用
json.Encoder并调用SetEscapeHTML(false),例如:enc := json.NewEncoder(w) enc.SetEscapeHTML(false) enc.Encode(v)
- 不要试图用
strings.ReplaceAll替换\u,容易破坏合法转义 - 该设置只影响 HTML 特殊字符(
<、>、&),对中文无副作用,放心用
fmt.Printf("raw: %s\n", s),比猜半天快得多。


















