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

如何动态处理Go语言中两种格式的JSON错误响应?

动态处理两种JSON错误响应格式的问题

错误响应格式

存在两种不同的JSON错误响应格式:

Error Type 1

{
  "error": "This is bad request"
}

Error Type 2

{
  "error": {
    "message": "This is error message"
  }
}

当前问题

现有代码仅能正常处理Error Type 2,处理Error Type 1时会触发panic:

panic: reflect: Elem of invalid type string

goroutine 1 [running]:
reflect.(*rtype).Elem(0x100a88a80)
        /usr/local/go/src/reflect/type.go:954 +0x194
main.main()
        /Users/username/Documents/dev/go/prac.go:31 +0x104
exit status 2

处理Error Type 2时输出正常:

This is error message

现有代码

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

func main() {

    // Error Type: 1
    str1 := "{\"error\":\"This is bad request\"}"
    var errResp interface{}
    json.Unmarshal([]byte(str1), &errResp)

    // ------------------------------------------------------------------------

    // Error Type: 2
    // str2 := "{\"error\": {\"message\": \"This is error message\"}}"
    // var errResp interface{}
    // json.Unmarshal([]byte(str2), &errResp)

    // ------------------------------------------------------------------------

    // Handling both type dynamically
    errResponse := errResp.(map[string]interface{})
    realErr := errResponse["error"]
    if reflect.TypeOf(realErr).Elem().Kind() == reflect.String {
        fmt.Println(fmt.Sprint(realErr))
    }
    lastRealErr := realErr.(map[string]interface{})
    fmt.Println(fmt.Sprint(lastRealErr["message"]))
}

解决方案

问题出在reflect.TypeOf(realErr).Elem()的调用:当realErr是字符串类型时,Elem()方法仅对指针、接口等复合类型有效,直接调用会触发panic。改用类型断言的ok模式可以安全区分两种错误类型,避免panic:

修改后的代码

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    // 测试Error Type 1
    str1 := "{\"error\":\"This is bad request\"}"
    var errResp interface{}
    json.Unmarshal([]byte(str1), &errResp)

    // 测试Error Type 2,取消注释即可
    // str2 := "{\"error\": {\"message\": \"This is error message\"}}"
    // var errResp interface{}
    // json.Unmarshal([]byte(str2), &errResp)

    errResponse := errResp.(map[string]interface{})
    realErr := errResponse["error"]

    // 优先判断是否为字符串类型的错误
    if errStr, ok := realErr.(string); ok {
        fmt.Println(errStr)
    } else if errMap, ok := realErr.(map[string]interface{}); ok {
        // 断言message字段为字符串,避免类型不匹配的问题
        if msg, ok := errMap["message"].(string); ok {
            fmt.Println(msg)
        }
    }
}

关键说明

  1. 用realErr.(string)配合ok值判断是否为Error Type 1,这种方式不会触发panic
  2. 若不是字符串,则尝试断言为map[string]interface{},对应Error Type 2,再取出message字段
  3. 对message字段也增加了类型断言,避免字段不存在或类型不匹配的潜在问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 20:24:22