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

Go如何反序列化混合类型JSON数组?aigaming客户端错误处理

解决Go中解析混合类型数组的JSON响应问题

我刚好处理过类似的混合类型JSON解析场景,针对你遇到的stackTrace是混合类型数组的数组这个问题,给你几个实用的解决方案:

方案一:直接用[][]interface{}接收混合数组

这是最直接的方式,因为interface{}可以容纳Go中的任意类型,刚好匹配JSON里的混合元素:

// 定义错误响应结构体
type ErrorResponse struct {
    Message     string          `json:"message"`
    StackTrace  [][]interface{} `json:"stackTrace"` // 用二维interface{}数组接收
    // 其他返回字段按需添加
}

解析后,你可以通过类型断言来访问数组里的具体值,比如假设每个子数组的第一个元素是函数名字符串,第二个是行号数字:

// 解析响应
var resp ErrorResponse
if err := json.Unmarshal(responseBody, &resp); err != nil {
    // 处理解析错误
    log.Fatal(err)
}

// 遍历stackTrace处理每个帧
for _, frame := range resp.StackTrace {
    // 断言函数名
    if funcName, ok := frame[0].(string); ok {
        fmt.Printf("调用函数: %s\n", funcName)
    }
    // 断言行号(JSON数字默认解析为float64,需要转int)
    if lineNum, ok := frame[1].(float64); ok {
        fmt.Printf("行号: %d\n", int(lineNum))
    }
}

这个方案的优点是快速实现,适合stackTrace结构不固定的场景;缺点是每次访问都要做类型断言,代码稍显繁琐。

方案二:自定义UnmarshalJSON映射到结构化类型

如果stackTrace的子数组元素顺序是固定的(比如每个子数组都是[函数名, 行号, 文件路径]这样的组合),可以自定义解析逻辑,把混合数组映射到更清晰的结构体,后续使用更方便:

// 定义单个栈帧的结构体
type StackFrame struct {
    FuncName string
    LineNum  int
    FilePath string
}

// 错误响应结构体
type ErrorResponse struct {
    Message     string        `json:"message"`
    StackTrace  []StackFrame  `json:"stackTrace"`
    // 其他字段...
}

// 自定义UnmarshalJSON方法,处理混合数组的解析
func (e *ErrorResponse) UnmarshalJSON(data []byte) error {
    // 先定义临时结构体,用[][]interface{}接收原始stackTrace
    type TempResp struct {
        Message     string          `json:"message"`
        StackTrace  [][]interface{} `json:"stackTrace"`
        // 其他字段要和ErrorResponse保持一致
    }

    var temp TempResp
    if err := json.Unmarshal(data, &temp); err != nil {
        return err
    }

    // 把临时的混合数组转换为[]StackFrame
    frames := make([]StackFrame, len(temp.StackTrace))
    for i, arr := range temp.StackTrace {
        var frame StackFrame
        // 按顺序断言每个元素,注意处理类型不匹配的情况
        if len(arr) >= 1 {
            frame.FuncName, _ = arr[0].(string)
        }
        if len(arr) >= 2 {
            lineFloat, _ := arr[1].(float64)
            frame.LineNum = int(lineFloat)
        }
        if len(arr) >= 3 {
            frame.FilePath, _ = arr[2].(string)
        }
        frames[i] = frame
    }

    // 赋值给最终的ErrorResponse
    e.Message = temp.Message
    e.StackTrace = frames
    // 其他字段同理赋值...
    return nil
}

这样解析后,你可以直接像访问普通结构体字段一样使用resp.StackTrace[i].FuncName,不需要再做类型断言,代码更整洁。

注意事项

  • JSON中的数字类型默认会被解析为float64,如果需要转成int,一定要先做类型断言再转换,避免直接强制转换导致的错误。
  • 类型断言时一定要加上ok判断,防止因为类型不匹配导致panic。
  • 如果stackTrace的子数组元素类型和顺序完全不固定,建议优先用方案一,保持灵活性。

内容的提问来源于stack exchange,提问作者Nikole

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:40:01