You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 16:24:07