英文:
Dynamically handling the responses
问题
我正在尝试动态管理错误并获取适当的消息。有两种类型的错误响应-如下所示:
<li>错误类型1
{
"error": "This is bad request"
}
<li>错误类型2
{
"error": {
"message": "This is error message"
}
}
我在stackoverflow上尝试了各种答案,但无法找到可能的解决方案。根据我目前的代码,它适用于错误类型2
。
对于错误类型1
,我得到了错误:
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
对于错误类型2
,我得到了完美的输出:
This is error message
package main
import (
"encoding/json"
"fmt"
"reflect"
)
func main() {
// 错误类型:1
str1 := "{\"error\":\"This is bad request\"}"
var errResp interface{}
json.Unmarshal([]byte(str1), &errResp)
// ------------------------------------------------------------------------
// 错误类型: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 reflect.TypeOf(realErr).Elem().Kind() == reflect.String {
// 这里我使用了fmt.Sprint,因为我将在我的原始实现中将其返回为字符串。
fmt.Println(fmt.Sprint(realErr))
}
lastRealErr := realErr.(map[string]interface{})
fmt.Println(fmt.Sprint(lastRealErr["message"]))
}
在上面的代码中,我将两种错误类型的代码组合在一起。要进行测试,您只需注释一个并取消注释另一个即可。
你能帮我解决这个问题吗?谢谢。
英文:
I am trying to dynamically manage the error and get the appropriate message. There are two sort of error responses - below shared:
<li>Error Type 1
{
"error": "This is bad request"
}
<li>Error Type 2
{
"error": {
"message": "This is error message"
}
}
I tried with various answers on stackoverflow. But couldn't reach a possible solution. With the code I have currently, its working for one - Error Type 2
.
For Error Type 1
, I am getting error:
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
For Error Type 2
, I am getting perfect output:
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 {
// I have used fmt.Sprint here, because I will have to
// return it as string in my original implementation.
fmt.Println(fmt.Sprint(realErr))
}
lastRealErr := realErr.(map[string]interface{})
fmt.Println(fmt.Sprint(lastRealErr["message"]))
}
Here ^, I have combined the code for both the error types. To test it you will just have to comment one and uncomment the other to test.
Can you please help me out here? Thank you.
答案1
得分: 2
声明一个自定义类型来表示错误,并让它实现json.Unmarshaler
接口。在实现中,你可以查看原始数据,并根据数据的内容决定如何进行反序列化。
type response struct {
Error responseError
}
type responseError struct {
Message string
}
func (e *responseError) UnmarshalJSON(data []byte) error {
if len(data) == 0 || string(data) == `null` { // 什么都没有?
return nil
}
if data[0] == '"' && data[len(data)-1] == '"' { // 字符串?
return json.Unmarshal(data, &e.Message)
}
// 通过声明一个与responseError具有相同结构但没有方法的新类型,避免无限递归。
type E responseError
return json.Unmarshal(data, (*E)(e))
}
当encoding/json
包在目标值中遇到一个有效的json.Unmarshaler
实例时,它会自动调用UnmarshalJSON
方法。
https://go.dev/play/p/jWzRSsSuN65
英文:
Declare a custom type for the error and have it implement the json.Unmarshaler
interface. In the implementation you can look at the raw data and, based on what the data seems to contain, decide on how to unmarshal it.
type response struct {
Error responseError
}
type responseError struct {
Message string
}
func (e *responseError) UnmarshalJSON(data []byte) error {
if len(data) == 0 || string(data) == `null` { // nothing?
return nil
}
if data[0] == '"' && data[len(data)-1] == '"' { // string?
return json.Unmarshal(data, &e.Message)
}
// avoid infinite recursion by declaring a new type
// with same structure as responseError but no methods.
type E responseError
return json.Unmarshal(data, (*E)(e))
}
The encoding/json
package will automatically invoke the UnmarshalJSON
method when it encounters a valid instance of json.Unmarshaler
in the target value.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论