Allows users to check:
errors.Is(err, &UnmarshalTypeError{})
errors.Is(err, &UnmarshalFieldError{})
errors.Is(err, &InvalidUnmarshalError{})
errors.Is(err, &UnsupportedValueError{})
errors.Is(err, &MarshalerError{})
which is the recommended way of checking for kinds of errors.
SyntaxError.Is was implemented in CL 253037.
As and Unwrap relevant methods will be added in future CLs.
Change-Id: I1f8a503b8fdc0f3afdfe9669a91f3af8d960e028
GitHub-Last-Rev:
930cda5384c987a0b31f277ba3b4ab690ea74ac3
GitHub-Pull-Request: golang/go#41360
Reviewed-on: https://go-review.googlesource.com/c/go/+/254537
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Trust: Emmanuel Odeke <emm.odeke@gmail.com>
return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
}
+// Is returns true if target is a UnmarshalTypeError.
+func (e *UnmarshalTypeError) Is(target error) bool {
+ _, ok := target.(*UnmarshalTypeError)
+ return ok
+}
+
// An UnmarshalFieldError describes a JSON object key that
// led to an unexported (and therefore unwritable) struct field.
//
return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String()
}
+// Is returns true if target is a UnmarshalFieldError.
+func (e *UnmarshalFieldError) Is(target error) bool {
+ _, ok := target.(*UnmarshalFieldError)
+ return ok
+}
+
// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
// (The argument to Unmarshal must be a non-nil pointer.)
type InvalidUnmarshalError struct {
Type reflect.Type
}
+// Is returns true if target is a InvalidUnmarshalError.
+func (e *InvalidUnmarshalError) Is(target error) bool {
+ _, ok := target.(*InvalidUnmarshalError)
+ return ok
+}
+
func (e *InvalidUnmarshalError) Error() string {
if e.Type == nil {
return "json: Unmarshal(nil)"
}
}
}
+
+func TestInvalidUnmarshalErrorIs(t *testing.T) {
+ err := fmt.Errorf("apackage: %w: failed to parse struct", &InvalidUnmarshalError{reflect.TypeOf("a")})
+ if !errors.Is(err, &InvalidUnmarshalError{}) {
+ t.Fatalf("%v should be unwrapped to a InvalidUnmarshalError", err)
+ }
+}
+
+func TestUnmarshalFieldErrorIs(t *testing.T) {
+ err := fmt.Errorf("apackage: %w: failed to parse struct", &UnmarshalFieldError{
+ Key: "foo",
+ Type: reflect.TypeOf("a"),
+ Field: reflect.StructField{Name: "b"},
+ })
+ if !errors.Is(err, &UnmarshalFieldError{}) {
+ t.Fatalf("%v should be unwrapped to a UnmarshalFieldError", err)
+ }
+}
+
+func TestUnmarshalTypeErrorIs(t *testing.T) {
+ err := fmt.Errorf("apackage: %w: failed to parse struct", &UnmarshalTypeError{
+ Value: "foo",
+ Type: reflect.TypeOf("a"),
+ Offset: 1,
+ Struct: "Foo",
+ Field: "Bar",
+ })
+ if !errors.Is(err, &UnmarshalTypeError{}) {
+ t.Fatalf("%v should be unwrapped to a UnmarshalTypeError", err)
+ }
+}
return "json: unsupported value: " + e.Str
}
+// Is returns true if target is a UnsupportedValueError.
+func (e *UnsupportedValueError) Is(target error) bool {
+ _, ok := target.(*UnsupportedValueError)
+ return ok
+}
+
// Before Go 1.2, an InvalidUTF8Error was returned by Marshal when
// attempting to encode a string value with invalid UTF-8 sequences.
// As of Go 1.2, Marshal instead coerces the string to valid UTF-8 by
// Unwrap returns the underlying error.
func (e *MarshalerError) Unwrap() error { return e.Err }
+// Is returns true if target is a MarshalerError.
+func (e *MarshalerError) Is(target error) bool {
+ _, ok := target.(*MarshalerError)
+ return ok
+}
+
var hex = "0123456789abcdef"
// An encodeState encodes JSON into a bytes.Buffer.
import (
"bytes"
"encoding"
+ "errors"
"fmt"
"log"
"math"
func TestUnsupportedValues(t *testing.T) {
for _, v := range unsupportedValues {
if _, err := Marshal(v); err != nil {
- if _, ok := err.(*UnsupportedValueError); !ok {
+ if !errors.Is(err, &UnsupportedValueError{}) {
t.Errorf("for %v, got %T want UnsupportedValueError", v, err)
}
} else {
}
}
}
+
+func TestMarshalerErrorIs(t *testing.T) {
+ err := fmt.Errorf("apackage: %w: failed to parse struct", &MarshalerError{
+ reflect.TypeOf("a"),
+ fmt.Errorf("something"),
+ "TestMarshalerErrorIs",
+ })
+ if !errors.Is(err, &MarshalerError{}) {
+ t.Fatalf("%v should be unwrapped to a MarshalerError", err)
+ }
+}
+
+func TestUnsupportedValueErrorIs(t *testing.T) {
+ err := fmt.Errorf("apackage: %w: failed to parse struct", &UnsupportedValueError{
+ Value: reflect.Value{},
+ Str: "Foo",
+ })
+ if !errors.Is(err, &UnsupportedValueError{}) {
+ t.Fatalf("%v should be unwrapped to a UnsupportedValueError", err)
+ }
+}