
本文详解如何为 REST API 返回的嵌套 JSON 设计 Go 结构体,并指出原始响应中 Fruits: {[...]} 属于语法错误的 JSON,必须修正为标准数组格式 Fruits: [...] 才能被 json.Unmarshal 正确解析。
本文详解如何为 rest api 返回的嵌套 json 设计 go 结构体,并指出原始响应中 `fruits: {[...]}` 属于语法错误的 json,必须修正为标准数组格式 `fruits: [...]` 才能被 `json.unmarshal` 正确解析。
在 Go 中实现 JSON 反序列化(unmarshal)的关键前提是:输入 JSON 必须是合法、符合 RFC 8259 规范的文本。您提供的原始响应片段:
"Basket" : {
"Count": 1,
"Fruits": {[
{ "Name":"Mango", "Season":"Summer" },
{ "Name":"Fig", "Season":"Winter" }
]}
}⚠️ 这不是有效 JSON —— {[...]} 是非法语法:花括号 {} 表示对象(key-value 映射),方括号 [] 表示数组,二者不可直接嵌套成 {[...]}。JSON 解析器(包括 Go 的 encoding/json)会直接返回 invalid character '{' looking for beginning of value 或类似错误。
✅ 正确的 JSON 应为:
{
"Basket": {
"Count": 1,
"Fruits": [
{ "Name": "Mango", "Season": "Summer" },
{ "Name": "Fig", "Season": "Winter" }
]
}
}对应地,Go 结构体需严格匹配 JSON 的嵌套层级与字段名。由于顶层键是 "Basket",而非直接展开 Count 和 Fruits,您的原始模型缺少外层容器:
// ✅ 正确结构体定义(含嵌套 Basket 字段)
type Response struct {
Basket Basket `json:"Basket"`
}
type Basket struct {
Count int `json:"Count"`
Fruits []Fruit `json:"Fruits"`
}
type Fruit struct {
Name string `json:"Name"`
Season string `json:"Season"`
}使用示例:
jsonData := `{"Basket":{"Count":1,"Fruits":[{"Name":"Mango","Season":"Summer"},{"Name":"Fig","Season":"Winter"}]}}`
var resp Response
if err := json.Unmarshal([]byte(jsonData), &resp); err != nil {
log.Fatal("Unmarshal failed:", err) // 若 JSON 无效,此处报错
}
fmt.Printf("Count: %d, First fruit: %+v\n", resp.Basket.Count, resp.Basket.Fruits[0])
// 输出:Count: 1, First fruit: {Name:Mango Season:Summer}? 关键注意事项:
-
json:"key"标签必须与 JSON 中的实际字段名完全一致(区分大小写); - 嵌套结构不可省略中间层级(如
Basket); - Go 的
json.Marshal生成的是标准格式(如"Fruits":[...]),它不会也不应输出{[...]}—— 因为那根本不是 JSON; - 若服务端确实返回
{[...]},说明后端存在严重 Bug,必须由服务提供方修复 JSON 序列化逻辑(例如误用map[string]interface{}手动拼接,或混淆了json.RawMessage用法)。
? 验证建议:
在开发中,始终用 JSONLint 或 jq 校验响应体;在 Go 测试中添加断言:
if !json.Valid([]byte(rawJSON)) {
t.Fatal("invalid JSON received from API")
}总结:Go 的结构体建模本身没有问题,问题根源在于输入数据违反 JSON 规范。正确的做法是——坚持标准、拒绝非法输入、推动上游修复。只有合法 JSON + 匹配结构体,才能实现健壮可靠的反序列化。


















