如何动态处理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) } } }
关键说明
- 用
realErr.(string)配合ok值判断是否为Error Type 1,这种方式不会触发panic - 若不是字符串,则尝试断言为
map[string]interface{},对应Error Type 2,再取出message字段 - 对
message字段也增加了类型断言,避免字段不存在或类型不匹配的潜在问题
内容的提问来源于stack exchange,提问作者Serum
相关产品推荐
相关产品推荐

