]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/json: implement Is on all errors
authorCarlos Alexandro Becker <caarlos0@gmail.com>
Sun, 13 Sep 2020 02:12:02 +0000 (02:12 +0000)
committerEmmanuel Odeke <emm.odeke@gmail.com>
Sun, 13 Sep 2020 03:19:24 +0000 (03:19 +0000)
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>

src/encoding/json/decode.go
src/encoding/json/decode_test.go
src/encoding/json/encode.go
src/encoding/json/encode_test.go

index 86d8a69db7e6d76aa40ca9d4b307ea2f43e909b7..1b006ffb178d6285dc98c30fcdc9f3c3ad698723 100644 (file)
@@ -136,6 +136,12 @@ func (e *UnmarshalTypeError) Error() string {
        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.
 //
@@ -150,12 +156,24 @@ func (e *UnmarshalFieldError) Error() string {
        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)"
index 219e845c7b0b2cf47d6ffc2ca006715edb10e56e..b707dcfa9925e16eba721e6243460685aba634b9 100644 (file)
@@ -2572,3 +2572,34 @@ func TestUnmarshalMaxDepth(t *testing.T) {
                }
        }
 }
+
+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)
+       }
+}
index 578d551102de47da3bc9f38b143f7d968f34c278..8e6b342b595f210e38d59826c5323f53e056c110 100644 (file)
@@ -245,6 +245,12 @@ func (e *UnsupportedValueError) Error() string {
        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
@@ -279,6 +285,12 @@ func (e *MarshalerError) Error() string {
 // 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.
index 7290eca06f070769bf46225123ebde9c728294d6..90826a7f47672671e5ce0a70814ff8a570c493a5 100644 (file)
@@ -7,6 +7,7 @@ package json
 import (
        "bytes"
        "encoding"
+       "errors"
        "fmt"
        "log"
        "math"
@@ -211,7 +212,7 @@ var unsupportedValues = []interface{}{
 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 {
@@ -1155,3 +1156,24 @@ func TestMarshalerError(t *testing.T) {
                }
        }
 }
+
+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)
+       }
+}