常见原因是请求体未被完整读取或 Content-Type 不是 application/json,且 http.Request.Body 被重复读取导致为空;应检查 Content-Type、避免多次读取,必要时用 io.NopCloser 重置。
接收并解析 JSON 请求体时,json.Unmarshal 为什么总返回 invalid character
常见原因是请求体未被完整读取,或 Content-Type 不是 application/json,但服务端仍尝试解析。Go 的 http.Request.Body 是单次读取流,若之前被其他中间件(如日志、鉴权)调用过 io.ReadAll 或 r.ParseForm,后续再读就会得到空字节切片,导致 json.Unmarshal 解析空字符串而报错。
- 始终在解析前检查
r.Header.Get("Content-Type")是否包含application/json - 避免重复读取
r.Body;如需多次使用,用io.NopCloser(bytes.NewBuffer(buf))重置 - 用
io.LimitReader(r.Body, 1 限制最大读取 1MB,防止恶意大 payload
结构体字段无法反序列化?注意 json tag 和导出规则
Go 中只有首字母大写的导出字段才能被 json 包访问。若字段名是 userID 但没加 tag,JSON 中的 user_id 就无法绑定——默认映射是严格按 Go 字段名转蛇形,不会自动猜。
- 显式声明
jsontag:UserID int `json:"user_id"` - 忽略空字段用
omitempty:Name string `json:"name,omitempty"` - 嵌套结构体字段也需导出,否则整个嵌套对象为
null - 数字类型建议统一用
int64或float64,避免 JSON 数字解析成float64后再转int丢精度
处理不确定结构的 JSON:用 map[string]interface{} 还是 json.RawMessage
map[string]interface{} 看似灵活,但会把所有数字转成 float64,嵌套深时类型断言极易 panic;而 json.RawMessage 是延迟解析的原始字节切片,适合只提取部分字段或透传。