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?
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"`
}
https://go.dev/play/p/U7FBiA9qB54
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With