encoding/json: implement Is on SyntaxError

Allows users to check:

      errors.Is(err, &json.SyntaxError{})

which is the recommended way of checking for kinds of errors.

Change-Id: I20dc805f20212765e9936a82d9cb7822e73ec4ef
GitHub-Last-Rev: e2627ccf8e2a00cc3459bb9fee86c3c8675a33af
GitHub-Pull-Request: golang/go#41210
Reviewed-on: https://go-review.googlesource.com/c/go/+/253037
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/encoding/json/scanner.go b/src/encoding/json/scanner.go
index 9dc1903..05218f9 100644
--- a/src/encoding/json/scanner.go
+++ b/src/encoding/json/scanner.go
@@ -49,6 +49,12 @@
 
 func (e *SyntaxError) Error() string { return e.msg }
 
+// Is returns true if target is a SyntaxError.
+func (e *SyntaxError) Is(target error) bool {
+	_, ok := target.(*SyntaxError)
+	return ok
+}
+
 // A scanner is a JSON scanning state machine.
 // Callers call scan.reset and then pass bytes in one at a time
 // by calling scan.step(&scan, c) for each byte.
diff --git a/src/encoding/json/scanner_test.go b/src/encoding/json/scanner_test.go
index 3737516..c12d9bf 100644
--- a/src/encoding/json/scanner_test.go
+++ b/src/encoding/json/scanner_test.go
@@ -6,6 +6,8 @@
 
 import (
 	"bytes"
+	"errors"
+	"fmt"
 	"math"
 	"math/rand"
 	"reflect"
@@ -201,6 +203,13 @@
 	}
 }
 
+func TestSyntaxErrorIs(t *testing.T) {
+	err := fmt.Errorf("apackage: %w: failed to parse struct", &SyntaxError{"some error", 43})
+	if !errors.Is(err, &SyntaxError{}) {
+		t.Fatalf("%v should be unwrapped to a SyntaxError", err)
+	}
+}
+
 func diff(t *testing.T, a, b []byte) {
 	for i := 0; ; i++ {
 		if i >= len(a) || i >= len(b) || a[i] != b[i] {