
本文解析 Go 中常见的 JSON 反序列化错误 “json: cannot unmarshal string into Go value of type main.test_struct”,核心原因在于前端以表单编码(x-www-form-urlencoded)方式发送数据,而非合法 JSON 格式,导致 Go 的 json.Decoder 试图将形如 lat=...&lng=... 的字符串解析为结构体而失败。
本文解析 go 中常见的 json 反序列化错误 “json: cannot unmarshal string into go value of type main.test_struct”,核心原因在于前端以表单编码(x-www-form-urlencoded)方式发送数据,而非合法 json 格式,导致 go 的 `json.decoder` 试图将形如 `lat=...&lng=...` 的字符串解析为结构体而失败。
该错误并非 Go 类型定义或 JSON 标签问题,而是请求内容格式与解码器预期严重不匹配所致。
从你提供的前端代码可见:
var params = {long: long, lat: lat};
$.ajax({
type: 'POST',
url: url_bis,
data: params, // ← 关键:jQuery 默认将对象转为 x-www-form-urlencoded 字符串
dataType: 'jsonp',
// ...
});
此时实际发送的 HTTP 请求体是:
lat=48.892423&long=2.215331
⚠️ 注意:字段名是 long(非 lng),且缺少 acc;同时整个载荷是 URL 编码的键值对,不是 JSON 字符串。而你的 Go 服务却用 json.NewDecoder(r.Body).Decode(&t) 强制按 JSON 解析——这就像用 PDF 阅读器打开一个 TXT 文件,自然报错:“无法将字符串(lat=...)反序列化为 test_struct”。
✅ 正确解决方案(二选一)
方案一:前端改为发送标准 JSON(推荐)
修改 JavaScript,显式构造 JSON 并设置请求头:
const payload = JSON.stringify({
lat: data.location.lat,
lng: data.location.lng,
acc: 1962 // 或从其他来源获取
});
$.ajax({
type: 'POST',
url: url_bis,
contentType: 'application/json; charset=utf-8', // ← 告诉后端这是 JSON
data: payload,
success: function(data2) {
console.log(data2);
}
});
方案二:后端适配表单数据(兼容旧逻辑)
若无法修改前端,改用 r.FormValue 或 r.ParseForm() 提取字段:
func postGeo(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
http.Error(w, "Invalid form data", http.StatusBadRequest)
return
}
t := test_struct{}
t.Lat = float32(parseFloat32(r.FormValue("lat")))
t.Lng = float32(parseFloat32(r.FormValue("long"))) // 注意字段名是 "long"
t.Acc = parseInt(r.FormValue("acc"))
Info.Printf("Parsed: %+v", t)
w.Header().Set("Access-Control-Allow-Origin", "*")
fmt.Fprintf(w, "200")
}
// 辅助函数(生产环境建议用 strconv.ParseFloat + error 检查)
func parseFloat32(s string) float64 {
f, _ := strconv.ParseFloat(s, 32)
return f
}
func parseInt(s string) int {
i, _ := strconv.Atoi(s)
return i
}
? 验证与调试建议
- 在 Go 中先打印原始请求体,确认真实格式:
body, _ := io.ReadAll(r.Body) Info.Printf("Raw body: %s", string(body)) - 永远检查
r.Header.Get("Content-Type"),区分application/json与application/x-www-form-urlencoded。 - 结构体字段标签需与实际 JSON key 严格一致(如
"lng"vs"long"),大小写敏感。
? 总结:Go 的
json.Unmarshal/json.Decoder只接受合法 JSON 文本。当收到非 JSON 载荷(如表单、纯文本、XML)时,必须切换解析策略——切勿强行用 JSON 解码器“硬解”。明确前后端约定的数据格式,是避免此类错误的根本。











