英文:
How to accommodate for 2 different types of the same field when parsing JSON
问题
我正在使用一个JSON REST API,它可以返回相同字段的两种不同类型。
这是API的一个示例响应:
"result": {
"value": {
"error": "Invalid data",
"logs": []
}
},
但有时它也会返回以下内容:
"result": {
"value": {
"error": {
"msg": "Rate limit exceeded"
},
"logs": []
}
},
如你所见,error
字段可以变成一个对象。
以下是我在代码中定义的类型:
type ApiResponse struct {
Result struct {
Value struct {
Error string `json:"error"`
Logs []string `json:"logs"`
} `json:"value"`
} `json:"result"`
}
但由于error
的类型可能会变化,这在JSON解组时有时会引发问题:json: cannot unmarshal object into Go struct field .result.value.error of type string
我该如何处理这种情况?
英文:
I'm working with a JSON rest api that can return 2 different types of the same field.
Here's an example response from the api:
"result": {
"value": {
"error": "Invalid data",
"logs": [],
}
},
But sometimes it also returns this
"result": {
"value": {
"error": {
"msg": "Rate limit exceeded"
},
"logs": []
}
},
As you can see the error
field can change to an object.
Here's how i have defined the type in my code
type ApiResponse struct {
Result struct {
Value struct {
Error string `json:"error"`
Logs []string `json:"logs"`
} `json:"value"`
} `json:"result"`
}
But since the type of error can change, this sometimes causes issues when JSON unmarshaling: json: cannot unmarshal object into Go struct field .result.value.error of type string
How can i deal with this scenario?
答案1
得分: 4
你可以实现json.Unmarshaler
接口来自定义如何解码错误字段。
type ErrorMessage struct {
Text string
}
func (e *ErrorMessage) 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.Text)
}
if data[0] == '{' && data[len(data)-1] == '}' { // 对象?
type T struct {
Text string `json:"msg"`
}
return json.Unmarshal(data, (*T)(e))
}
return fmt.Errorf("不支持的错误消息类型")
}
然后将ApiResponse
类型的Error
字段更新为ErrorMessage
类型。
type ApiResponse struct {
Result struct {
Value struct {
Error ErrorMessage `json:"error"`
Logs []string `json:"logs"`
} `json:"value"`
} `json:"result"`
}
https://go.dev/play/p/U7FBiA9qB54
英文:
You can implement the json.Unmarshaler
interface to customize how the error field will be decoded.
type ErrorMessage struct {
Text string
}
func (e *ErrorMessage) UnmarshalJSON(data []byte) error {
if len(data) == 0 || string(data) == "null" {
return nil
}
if data[0] == '"' && data[len(data)-1] == '"' { // string?
return json.Unmarshal(data, &e.Text)
}
if data[0] == '{' && data[len(data)-1] == '}' { // object?
type T struct {
Text string `json:"msg"`
}
return json.Unmarshal(data, (*T)(e))
}
return fmt.Errorf("unsupported error message type")
}
Then update the ApiResponse
type's Error
field to be of type ErrorMessage
.
type ApiResponse struct {
Result struct {
Value struct {
Error ErrorMessage `json:"error"`
Logs []string `json:"logs"`
} `json:"value"`
} `json:"result"`
}
答案2
得分: 0
由于接口Error
被定义为字符串,你需要一个实现了Error接口的自定义类型错误对象,该对象可能返回msg
。然后创建自己的解组方法来处理可能的JSON字符串。
英文:
As interface Error
is defined as string, you need a custom type error object implementing the Error interface - which returns msg
probably. Then create your own unmarshalling method which handles the possible json strings.
答案3
得分: 0
将您的结构定义如下:
type ApiResponse struct {
Result struct {
Value struct {
Error interface{} `json:"error"`
Logs []string `json:"logs"`
} `json:"value"`
} `json:"result"`
}
将其解组为类型为ApiResponse
的变量(假设为data
)。然后可以按如下方式检查Error
的类型:
switch v := data.Result.Value.Error.(type) {
case string:
// 第一种情况
case map[string]interface{}:
// 第二种情况,读取键"msg"
default:
fmt.Printf("我不知道类型 %T!\n", v)
}
英文:
Define your structure as follows:
type ApiResponse struct {
Result struct {
Value struct {
Error interface{}`json:"error"`
Logs []string `json:"logs"`
} `json:"value"`
} `json:"result"`
}
Unmarshall into a variable of type ApiResponse
(lets assume data
). The type of Error
then can be checked as follows:
switch v := data.Result.Value.Error.(type) {
case string:
// 1st case
case map[string]interface{}:
// 2nd case, read key "msg"
default:
fmt.Printf("I don't know about type %T!\n", v)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论