Skip to content

Instantly share code, notes, and snippets.

@gagliardetto
Created June 22, 2018 19:39
Show Gist options
  • Save gagliardetto/d3c45a5cee6d943d5b51439960b082dd to your computer and use it in GitHub Desktop.
Save gagliardetto/d3c45a5cee6d943d5b51439960b082dd to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"errors"
"fmt"
)
type Notification struct {
Error error `json:"error"`
}
func main() {
err := errors.New("transmission")
notification := Notification{
Error: err,
}
rawJSON, err := json.Marshal(notification)
if err != nil {
panic(err)
}
fmt.Println(string(rawJSON))
}
@gagliardetto
Copy link
Author

gagliardetto commented Jun 22, 2018

Solution:

package main

import (
	"encoding/json"
	"errors"
	"fmt"
)

type Notification struct {
	Error error `json:"error"`
}

func main() {
	// The problem here is that `errors.New` returns a non-exported
	// object `errors.errorString` , which does satisfy the `error` interface,
	// but cannot be marshaled by json because it is unexported.
	err := errors.New("transmission error")
	notification := Notification{
		Error: err,
	}

	rawJSON, err := json.Marshal(notification)
	if err != nil {
		panic(err)
	}
	// The output of this is:
	// {"error":{}}
	fmt.Println(string(rawJSON))

	// If we use a custom error, we can make it marshal-able:
	err = NewError("transmission error")
	notification = Notification{
		Error: err,
	}
	rawJSON, err = json.Marshal(notification)
	if err != nil {
		panic(err)
	}
	// The output of this is:
	// {"error":{"error":"transmission error"}}
	fmt.Println(string(rawJSON))

}

type CustomError struct {
	ErrorString string `json:"error"`
}

//
func (err *CustomError) Error() string {
	return err.ErrorString
}

func NewError(err string) error {
	return &CustomError{
		ErrorString: err,
	}
}

// In most cases, we just want the error to be a simple string, so we will
// write a custom Marshal function which marshals `CustomError` to a string:

//func (u *CustomError) MarshalJSON() ([]byte, error) {
//	return json.Marshal(u.ErrorString)
//}
// If the above is uncommented, the output of `fmt.Println(string(rawJSON))`
// will be:
// {"error":"transmission error"}
//
// This is useful especially when you send errors to a DB that expects the
// fields to have a consistent schema, like ElasticSearch.

@gagliardetto
Copy link
Author

CC @mie00

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment