动态处理响应

huangapple go评论83阅读模式
英文:

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

{
  &quot;error&quot;: &quot;This is bad request&quot;
}

<li>Error Type 2

{
  &quot;error&quot;: {
    &quot;message&quot;: &quot;This is error message&quot;
  }
}

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 (
	&quot;encoding/json&quot;
	&quot;fmt&quot;
	&quot;reflect&quot;
)

func main() {

	// Error Type: 1

	str1 := &quot;{\&quot;error\&quot;:\&quot;This is bad request\&quot;}&quot;
	var errResp interface{}
	json.Unmarshal([]byte(str1), &amp;errResp)

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

	// Error Type: 2

	// str2 := &quot;{\&quot;error\&quot;: {\&quot;message\&quot;: \&quot;This is error message\&quot;}}&quot;
	// var errResp interface{}
	// json.Unmarshal([]byte(str2), &amp;errResp)

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

	// Handling both type dynamically

	errResponse := errResp.(map[string]interface{})
	realErr := errResponse[&quot;error&quot;]
	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[&quot;message&quot;]))
}

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] == &#39;&quot;&#39; &amp;&amp; data[len(data)-1] == &#39;&quot;&#39; { // string?
		return json.Unmarshal(data, &amp;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.

https://go.dev/play/p/jWzRSsSuN65

huangapple
  • 本文由 发表于 2022年8月17日 00:51:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/73377565.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定