使用ioutil.ReadAll解析嵌套Curl响应时Unmarshal失败:数组与对象结构不匹配问题的解决方法
解决Go JSON反序列化时数组与对象不匹配的问题
我刚碰到过一模一样的坑——第三方接口返回的JSON和文档完全不符,直接导致Unmarshal报错。给你拆解下问题和解决方案:
问题复盘
原本我预期接口返回的list是标准数组格式:
{ "code": 200, "message": "Success", "data": { "list": [ { "user": "user A", "status" : "normal" }, { "user": "user B", "status" : "normal" } ], "page": 1, "total_pages": 5000 } }
所以对应的Go结构体里把List定义成了切片:
type User struct { Code int `json:"code"` Message string `json:"message"` Data struct { List []struct { User string `json:"user"` Status string `json:"status"` } `json:"list"` Page int `json:"page"` TotalPages int `json:"total_pages"` } `json:"data"` }
但实际调用后发现,第三方返回的list是个以数字字符串为键的对象:
{ "code": 200, "message": "Success", "data": { "list": { "1": { "user": "user A", "status": "normal" }, "2": { "user": "user A", "status": "normal" } }, "page": 1, "total_pages": 2000 } }
这直接触发反序列化错误:decode slice: expect [ or n, but found {——程序本来要读数组([开头),结果读到了对象的起始符{,类型完全不匹配。
解决方案
核心就是把结构体里的List字段类型从切片改成字符串键的Map,匹配实际返回的JSON结构:
修改后的结构体
type User struct { Code int `json:"code"` Message string `json:"message"` Data struct { // 将[]struct{}替换为map[string]struct{},对应返回的键值对结构 List map[string]struct { User string `json:"user"` Status string `json:"status"` } `json:"list"` Page int `json:"page"` TotalPages int `json:"total_pages"` } `json:"data"` }
反序列化并转切片(可选)
如果你的业务逻辑还是需要用切片格式,可以在反序列化后遍历Map,把值提取成切片:
defer response.Body.Close() // 注意ioutil.ReadAll返回的就是[]byte,无需重复转换 ioResponse, err := ioutil.ReadAll(response.Body) if err != nil { log.Println("读取响应体失败:", err) return } var returnData User err = jsoniter.Unmarshal(ioResponse, &returnData) if err != nil { log.Println("JSON反序列化失败:", err) return } // 按需将Map转换为切片 var userSlice []struct { User string `json:"user"` Status string `json:"status"` } for _, userInfo := range returnData.Data.List { userSlice = append(userSlice, userInfo) } // 现在userSlice就是你最初预期的数组格式了
这样就能完美解决类型不匹配的问题,顺利完成反序列化啦。
内容的提问来源于stack exchange,提问作者yssachan
相关产品推荐
相关产品推荐

