Reputation: 12222
I am create API
in go
. Everything is working fine only that when there is an error I want to show it to the user. I am using go's errors
package.
Below is the sample
code:
type ErrorResponse struct {
Status string `json:"status"`
Error error `json:"error"`
}
err := errors.New("Total Price cannot be a negative value")
errRes := ErrorResponse{"ERROR", err}
response, errr := json.Marshal(errRes)
if errr != nil {
log.Fatal(err)
return
}
io.WriteString(w, string(response))
The response I am getting is:
{
"status": "ERROR",
"error": {} //why is this empty
}
error key should have string Total Price cannot be a negative value
. I don't understand the problem.
Upvotes: 0
Views: 4355
Reputation: 3274
Error types can't marshal themselves to JSON. There's a few ways to work around this. If you don't want to change your ErrorResponse
struct then pretty much the only way is to define a custom MarshalJSON
method for your struct where you tell the marshaler to use the string returned by the Error's .Error()
method.
func (resp ErrorResponse) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
Status string `json:"status"`
Error string `json:"error"`
}{
Status: resp.Status,
Error: resp.Error.Error(),
})
}
https://play.golang.org/p/EgVj_4Cc3W
If you want to marshal errors into JSON elsewhere also. Then you could use a custom error type and define marshaling for that, e.g:
type MyError struct {
Error error
}
func (err MyError) MarshalJSON() ([]byte, error) {
return json.Marshal(err.Error.Error())
}
https://play.golang.org/p/sjOHj9X0tO
Simplest (and probably the best) way is to just use a string in your response struct. It makes sense because the actual value you send in the http response is obviously a string, not an error interface.
type ErrorResponse struct {
Status string `json:"status"`
Error string `json:"error"`
}
err := errors.New("Total Price cannot be a negative value")
errRes := ErrorResponse{"ERROR", err.Error()}
response, errr := json.Marshal(errRes)
if errr != nil {
log.Fatal(err)
// you should write something to responseWriter w here before returning
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
io.WriteString(w, string(response))
Note that in case the marshaling fails, you should still write some kind of response before returning.
Upvotes: 7