New Upstream Release - golang-k8s-sigs-json

Ready changes

Summary

Merged new upstream version: 0.0~git20221116.bc3834c (was: 0.0~git20211208.9f7c6b3).

Resulting package

Built on 2022-12-18T05:07 (took 2m41s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-releases golang-k8s-sigs-json-dev

Lintian Result

Diff

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bdc0f9e..e6ec1c9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,6 +20,7 @@ jobs:
       with:
         go-version: "1.x"
         stable: true
+        check-latest: true
 
     - name: Test
       run: |
@@ -50,7 +51,7 @@ jobs:
       - name: Add GOBIN to PATH
         run: echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
       - name: Install dependencies
-        run: go get golang.org/x/exp/cmd/apidiff
+        run: go install golang.org/x/exp/cmd/apidiff@latest
       - name: Checkout old code
         uses: actions/checkout@v2
         with:
diff --git a/debian/changelog b/debian/changelog
index 53e5e4d..f64965f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+golang-k8s-sigs-json (0.0~git20221116.bc3834c-1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Sun, 18 Dec 2022 05:05:18 -0000
+
 golang-k8s-sigs-json (0.0~git20211208.9f7c6b3-2) unstable; urgency=medium
 
   * Source upload, no changed.
diff --git a/go.mod b/go.mod
index 6fad584..acef668 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
 module sigs.k8s.io/json
 
-go 1.17
+go 1.18
diff --git a/hack/verify-apidiff.sh b/hack/verify-apidiff.sh
index 7b23c8c..5594d20 100755
--- a/hack/verify-apidiff.sh
+++ b/hack/verify-apidiff.sh
@@ -65,7 +65,7 @@ fi
 if ! which apidiff > /dev/null; then
   echo "Installing golang.org/x/exp/cmd/apidiff..."
   pushd "${TMPDIR:-/tmp}" > /dev/null
-    go get golang.org/x/exp/cmd/apidiff
+    go install golang.org/x/exp/cmd/apidiff@latest
   popd > /dev/null
 fi
 
diff --git a/internal/golang/encoding/json/bench_test.go b/internal/golang/encoding/json/bench_test.go
index 1910f6a..635050b 100644
--- a/internal/golang/encoding/json/bench_test.go
+++ b/internal/golang/encoding/json/bench_test.go
@@ -191,7 +191,7 @@ func BenchmarkDecoderStream(b *testing.B) {
 	var buf bytes.Buffer
 	dec := NewDecoder(&buf)
 	buf.WriteString(`"` + strings.Repeat("x", 1000000) + `"` + "\n\n\n")
-	var x interface{}
+	var x any
 	if err := dec.Decode(&x); err != nil {
 		b.Fatal("Decode:", err)
 	}
diff --git a/internal/golang/encoding/json/decode.go b/internal/golang/encoding/json/decode.go
index 3a8b645..6a13cf2 100644
--- a/internal/golang/encoding/json/decode.go
+++ b/internal/golang/encoding/json/decode.go
@@ -75,6 +75,8 @@ import (
 // either be any string type, an integer, implement json.Unmarshaler, or
 // implement encoding.TextUnmarshaler.
 //
+// If the JSON-encoded data contain a syntax error, Unmarshal returns a SyntaxError.
+//
 // If a JSON value is not appropriate for a given target type,
 // or if a JSON number overflows the target type, Unmarshal
 // skips that field and completes the unmarshaling as best it can.
@@ -85,15 +87,14 @@ import (
 //
 // The JSON null value unmarshals into an interface, map, pointer, or slice
 // by setting that Go value to nil. Because null is often used in JSON to mean
-// ``not present,'' unmarshaling a JSON null into any other Go type has no effect
+// “not present,” unmarshaling a JSON null into any other Go type has no effect
 // on the value and produces no error.
 //
 // When unmarshaling quoted strings, invalid UTF-8 or
 // invalid UTF-16 surrogate pairs are not treated as an error.
 // Instead, they are replaced by the Unicode replacement
 // character U+FFFD.
-//
-func Unmarshal(data []byte, v interface{}, opts ...UnmarshalOpt) error {
+func Unmarshal(data []byte, v any, opts ...UnmarshalOpt) error {
 	// Check for well-formedness.
 	// Avoids filling out half a data structure
 	// before discovering a JSON syntax error.
@@ -167,16 +168,16 @@ func (e *InvalidUnmarshalError) Error() string {
 		return "json: Unmarshal(nil)"
 	}
 
-	if e.Type.Kind() != reflect.Ptr {
+	if e.Type.Kind() != reflect.Pointer {
 		return "json: Unmarshal(non-pointer " + e.Type.String() + ")"
 	}
 	return "json: Unmarshal(nil " + e.Type.String() + ")"
 }
 */
 
-func (d *decodeState) unmarshal(v interface{}) error {
+func (d *decodeState) unmarshal(v any) error {
 	rv := reflect.ValueOf(v)
-	if rv.Kind() != reflect.Ptr || rv.IsNil() {
+	if rv.Kind() != reflect.Pointer || rv.IsNil() {
 		return &InvalidUnmarshalError{reflect.TypeOf(v)}
 	}
 
@@ -233,7 +234,7 @@ type decodeState struct {
 	disallowUnknownFields bool
 
 	savedStrictErrors []error
-	seenStrictErrors  map[string]struct{}
+	seenStrictErrors  map[strictError]struct{}
 	strictFieldStack  []string
 
 	caseSensitive bool
@@ -425,7 +426,7 @@ type unquotedValue struct{}
 // quoted string literal or literal null into an interface value.
 // If it finds anything other than a quoted string literal or null,
 // valueQuoted returns unquotedValue{}.
-func (d *decodeState) valueQuoted() interface{} {
+func (d *decodeState) valueQuoted() any {
 	switch d.opcode {
 	default:
 		panic(phasePanicMsg)
@@ -467,7 +468,7 @@ func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnm
 	// If v is a named type and is addressable,
 	// start with its address, so that if the type has pointer methods,
 	// we find them.
-	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
+	if v.Kind() != reflect.Pointer && v.Type().Name() != "" && v.CanAddr() {
 		haveAddr = true
 		v = v.Addr()
 	}
@@ -476,14 +477,14 @@ func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnm
 		// usefully addressable.
 		if v.Kind() == reflect.Interface && !v.IsNil() {
 			e := v.Elem()
-			if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
+			if e.Kind() == reflect.Pointer && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Pointer) {
 				haveAddr = false
 				v = e
 				continue
 			}
 		}
 
-		if v.Kind() != reflect.Ptr {
+		if v.Kind() != reflect.Pointer {
 			break
 		}
 
@@ -678,7 +679,7 @@ func (d *decodeState) object(v reflect.Value) error {
 			reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
 			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 		default:
-			if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) {
+			if !reflect.PointerTo(t.Key()).Implements(textUnmarshalerType) {
 				d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)})
 				d.skip()
 				return nil
@@ -695,7 +696,7 @@ func (d *decodeState) object(v reflect.Value) error {
 					seenKeys = map[string]struct{}{}
 				}
 				if _, seen := seenKeys[fieldName]; seen {
-					d.saveStrictError(d.newFieldError("duplicate field", fieldName))
+					d.saveStrictError(d.newFieldError(duplicateStrictErrType, fieldName))
 				} else {
 					seenKeys[fieldName] = struct{}{}
 				}
@@ -711,7 +712,7 @@ func (d *decodeState) object(v reflect.Value) error {
 				var seenKeys uint64
 				checkDuplicateField = func(fieldNameIndex int, fieldName string) {
 					if seenKeys&(1<<fieldNameIndex) != 0 {
-						d.saveStrictError(d.newFieldError("duplicate field", fieldName))
+						d.saveStrictError(d.newFieldError(duplicateStrictErrType, fieldName))
 					} else {
 						seenKeys = seenKeys | (1 << fieldNameIndex)
 					}
@@ -724,7 +725,7 @@ func (d *decodeState) object(v reflect.Value) error {
 						seenIndexes = make([]bool, len(fields.list))
 					}
 					if seenIndexes[fieldNameIndex] {
-						d.saveStrictError(d.newFieldError("duplicate field", fieldName))
+						d.saveStrictError(d.newFieldError(duplicateStrictErrType, fieldName))
 					} else {
 						seenIndexes[fieldNameIndex] = true
 					}
@@ -808,7 +809,7 @@ func (d *decodeState) object(v reflect.Value) error {
 				subv = v
 				destring = f.quoted
 				for _, i := range f.index {
-					if subv.Kind() == reflect.Ptr {
+					if subv.Kind() == reflect.Pointer {
 						if subv.IsNil() {
 							// If a struct embeds a pointer to an unexported type,
 							// it is not possible to set a newly allocated value
@@ -836,7 +837,7 @@ func (d *decodeState) object(v reflect.Value) error {
 				d.errorContext.Struct = t
 				d.appendStrictFieldStackKey(f.name)
 			} else if d.disallowUnknownFields {
-				d.saveStrictError(d.newFieldError("unknown field", string(key)))
+				d.saveStrictError(d.newFieldError(unknownStrictErrType, string(key)))
 			}
 		}
 
@@ -874,7 +875,7 @@ func (d *decodeState) object(v reflect.Value) error {
 			kt := t.Key()
 			var kv reflect.Value
 			switch {
-			case reflect.PtrTo(kt).Implements(textUnmarshalerType):
+			case reflect.PointerTo(kt).Implements(textUnmarshalerType):
 				kv = reflect.New(kt)
 				if err := d.literalStore(item, kv, true); err != nil {
 					return err
@@ -934,7 +935,7 @@ func (d *decodeState) object(v reflect.Value) error {
 
 // convertNumber converts the number literal s to a float64 or a Number
 // depending on the setting of d.useNumber.
-func (d *decodeState) convertNumber(s string) (interface{}, error) {
+func (d *decodeState) convertNumber(s string) (any, error) {
 	if d.useNumber {
 		return Number(s), nil
 	}
@@ -1010,7 +1011,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
 			break
 		}
 		switch v.Kind() {
-		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
+		case reflect.Interface, reflect.Pointer, reflect.Map, reflect.Slice:
 			v.Set(reflect.Zero(v.Type()))
 			// otherwise, ignore null for primitives/string
 		}
@@ -1140,7 +1141,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
 // but they avoid the weight of reflection in this common case.
 
 // valueInterface is like value but returns interface{}
-func (d *decodeState) valueInterface() (val interface{}) {
+func (d *decodeState) valueInterface() (val any) {
 	switch d.opcode {
 	default:
 		panic(phasePanicMsg)
@@ -1157,14 +1158,14 @@ func (d *decodeState) valueInterface() (val interface{}) {
 }
 
 // arrayInterface is like array but returns []interface{}.
-func (d *decodeState) arrayInterface() []interface{} {
+func (d *decodeState) arrayInterface() []any {
 	origStrictFieldStackLen := len(d.strictFieldStack)
 	defer func() {
 		// Reset to original length and reuse the allocated space for the strict FieldStack slice.
 		d.strictFieldStack = d.strictFieldStack[:origStrictFieldStackLen]
 	}()
 
-	var v = make([]interface{}, 0)
+	var v = make([]any, 0)
 	for {
 		// Look ahead for ] - can only happen on first iteration.
 		d.scanWhile(scanSkipSpace)
@@ -1192,14 +1193,14 @@ func (d *decodeState) arrayInterface() []interface{} {
 }
 
 // objectInterface is like object but returns map[string]interface{}.
-func (d *decodeState) objectInterface() map[string]interface{} {
+func (d *decodeState) objectInterface() map[string]any {
 	origStrictFieldStackLen := len(d.strictFieldStack)
 	defer func() {
 		// Reset to original length and reuse the allocated space for the strict FieldStack slice.
 		d.strictFieldStack = d.strictFieldStack[:origStrictFieldStackLen]
 	}()
 
-	m := make(map[string]interface{})
+	m := make(map[string]any)
 	for {
 		// Read opening " of string key or closing }.
 		d.scanWhile(scanSkipSpace)
@@ -1231,7 +1232,7 @@ func (d *decodeState) objectInterface() map[string]interface{} {
 
 		if d.disallowDuplicateFields {
 			if _, exists := m[key]; exists {
-				d.saveStrictError(d.newFieldError("duplicate field", key))
+				d.saveStrictError(d.newFieldError(duplicateStrictErrType, key))
 			}
 		}
 
@@ -1258,7 +1259,7 @@ func (d *decodeState) objectInterface() map[string]interface{} {
 // literalInterface consumes and returns a literal from d.data[d.off-1:] and
 // it reads the following byte ahead. The first byte of the literal has been
 // read already (that's how the caller knows it's a literal).
-func (d *decodeState) literalInterface() interface{} {
+func (d *decodeState) literalInterface() any {
 	// All bytes inside literal return scanContinue op code.
 	start := d.readIndex()
 	d.rescanLiteral()
diff --git a/internal/golang/encoding/json/decode_test.go b/internal/golang/encoding/json/decode_test.go
index d3496d6..9c7fd35 100644
--- a/internal/golang/encoding/json/decode_test.go
+++ b/internal/golang/encoding/json/decode_test.go
@@ -31,7 +31,7 @@ type U struct {
 }
 
 type V struct {
-	F1 interface{}
+	F1 any
 	F2 int32
 	F3 Number
 	F4 *VOuter
@@ -62,18 +62,18 @@ func (*SS) UnmarshalJSON(data []byte) error {
 
 // ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and
 // without UseNumber
-var ifaceNumAsFloat64 = map[string]interface{}{
+var ifaceNumAsFloat64 = map[string]any{
 	"k1": float64(1),
 	"k2": "s",
-	"k3": []interface{}{float64(1), float64(2.0), float64(3e-3)},
-	"k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)},
+	"k3": []any{float64(1), float64(2.0), float64(3e-3)},
+	"k4": map[string]any{"kk1": "s", "kk2": float64(2)},
 }
 
-var ifaceNumAsNumber = map[string]interface{}{
+var ifaceNumAsNumber = map[string]any{
 	"k1": Number("1"),
 	"k2": "s",
-	"k3": []interface{}{Number("1"), Number("2.0"), Number("3e-3")},
-	"k4": map[string]interface{}{"kk1": "s", "kk2": Number("2")},
+	"k3": []any{Number("1"), Number("2.0"), Number("3e-3")},
+	"k4": map[string]any{"kk1": "s", "kk2": Number("2")},
 }
 
 type tx struct {
@@ -262,9 +262,9 @@ type Ambig struct {
 }
 
 type XYZ struct {
-	X interface{}
-	Y interface{}
-	Z interface{}
+	X any
+	Y any
+	Z any
 }
 
 type unexportedWithMethods struct{}
@@ -389,8 +389,8 @@ type mapStringToStringData struct {
 
 type unmarshalTest struct {
 	in                    string
-	ptr                   interface{} // new(type)
-	out                   interface{}
+	ptr                   any // new(type)
+	out                   any
 	err                   error
 	useNumber             bool
 	golden                bool
@@ -414,13 +414,13 @@ var unmarshalTests = []unmarshalTest{
 	{in: `-5`, ptr: new(int16), out: int16(-5)},
 	{in: `2`, ptr: new(Number), out: Number("2"), useNumber: true},
 	{in: `2`, ptr: new(Number), out: Number("2")},
-	{in: `2`, ptr: new(interface{}), out: float64(2.0)},
-	{in: `2`, ptr: new(interface{}), out: Number("2"), useNumber: true},
+	{in: `2`, ptr: new(any), out: float64(2.0)},
+	{in: `2`, ptr: new(any), out: Number("2"), useNumber: true},
 	{in: `"a\u1234"`, ptr: new(string), out: "a\u1234"},
 	{in: `"http:\/\/"`, ptr: new(string), out: "http://"},
 	{in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
 	{in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
-	{in: "null", ptr: new(interface{}), out: nil},
+	{in: "null", ptr: new(any), out: nil},
 	{in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7, "T", "X"}},
 	{in: `{"X": 23}`, ptr: new(T), out: T{}, err: &UnmarshalTypeError{"number", reflect.TypeOf(""), 8, "T", "X"}}, {in: `{"x": 1}`, ptr: new(tx), out: tx{}},
 	{in: `{"x": 1}`, ptr: new(tx), out: tx{}},
@@ -428,8 +428,8 @@ var unmarshalTests = []unmarshalTest{
 	{in: `{"S": 23}`, ptr: new(W), out: W{}, err: &UnmarshalTypeError{"number", reflect.TypeOf(SS("")), 0, "W", "S"}},
 	{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
 	{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true},
-	{in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64},
-	{in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true},
+	{in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(any), out: ifaceNumAsFloat64},
+	{in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(any), out: ifaceNumAsNumber, useNumber: true},
 
 	// raw values with whitespace
 	{in: "\n true ", ptr: new(bool), out: true},
@@ -472,10 +472,10 @@ var unmarshalTests = []unmarshalTest{
 	{in: `[1, 2, 3]`, ptr: new(MustNotUnmarshalJSON), err: errors.New("MustNotUnmarshalJSON was used")},
 
 	// empty array to interface test
-	{in: `[]`, ptr: new([]interface{}), out: []interface{}{}},
-	{in: `null`, ptr: new([]interface{}), out: []interface{}(nil)},
-	{in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}},
-	{in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}},
+	{in: `[]`, ptr: new([]any), out: []any{}},
+	{in: `null`, ptr: new([]any), out: []any(nil)},
+	{in: `{"T":[]}`, ptr: new(map[string]any), out: map[string]any{"T": []any{}}},
+	{in: `{"T":null}`, ptr: new(map[string]any), out: map[string]any{"T": any(nil)}},
 
 	// composite tests
 	{in: allValueIndent, ptr: new(All), out: allValue},
@@ -1103,7 +1103,7 @@ func TestUnmarshal(t *testing.T) {
 		}
 
 		typ := reflect.TypeOf(tt.ptr)
-		if typ.Kind() != reflect.Ptr {
+		if typ.Kind() != reflect.Pointer {
 			t.Errorf("#%d: unmarshalTest.ptr %T is not a pointer type", i, tt.ptr)
 			continue
 		}
@@ -1176,7 +1176,7 @@ func TestUnmarshal(t *testing.T) {
 
 func TestUnmarshalMarshal(t *testing.T) {
 	initBig()
-	var v interface{}
+	var v any
 	if err := Unmarshal(jsonBig, &v); err != nil {
 		t.Fatalf("Unmarshal: %v", err)
 	}
@@ -1248,7 +1248,7 @@ type Xint struct {
 
 func TestUnmarshalInterface(t *testing.T) {
 	var xint Xint
-	var i interface{} = &xint
+	var i any = &xint
 	if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil {
 		t.Fatalf("Unmarshal: %v", err)
 	}
@@ -1382,8 +1382,8 @@ type All struct {
 	PSmall  *Small
 	PPSmall **Small
 
-	Interface  interface{}
-	PInterface *interface{}
+	Interface  any
+	PInterface *any
 
 	unexported int
 }
@@ -1717,9 +1717,9 @@ func intpp(x *int) **int {
 }
 
 var interfaceSetTests = []struct {
-	pre  interface{}
+	pre  any
 	json string
-	post interface{}
+	post any
 }{
 	{"foo", `"bar"`, "bar"},
 	{"foo", `2`, 2.0},
@@ -1738,7 +1738,7 @@ var interfaceSetTests = []struct {
 
 func TestInterfaceSet(t *testing.T) {
 	for _, tt := range interfaceSetTests {
-		b := struct{ X interface{} }{tt.pre}
+		b := struct{ X any }{tt.pre}
 		blob := `{"X":` + tt.json + `}`
 		if err := Unmarshal([]byte(blob), &b); err != nil {
 			t.Errorf("Unmarshal %#q: %v", blob, err)
@@ -1768,7 +1768,7 @@ type NullTest struct {
 	PBool     *bool
 	Map       map[string]string
 	Slice     []string
-	Interface interface{}
+	Interface any
 
 	PRaw    *RawMessage
 	PTime   *time.Time
@@ -1989,7 +1989,7 @@ func TestSliceOfCustomByte(t *testing.T) {
 }
 
 var decodeTypeErrorTests = []struct {
-	dest interface{}
+	dest any
 	src  string
 }{
 	{new(string), `{"user": "name"}`}, // issue 4628.
@@ -2022,7 +2022,7 @@ var unmarshalSyntaxTests = []string{
 }
 
 func TestUnmarshalSyntax(t *testing.T) {
-	var x interface{}
+	var x any
 	for _, src := range unmarshalSyntaxTests {
 		err := Unmarshal([]byte(src), &x)
 		if _, ok := err.(*SyntaxError); !ok {
@@ -2035,8 +2035,8 @@ func TestUnmarshalSyntax(t *testing.T) {
 // Issue 4660
 type unexportedFields struct {
 	Name string
-	m    map[string]interface{} `json:"-"`
-	m2   map[string]interface{} `json:"abcd"`
+	m    map[string]any `json:"-"`
+	m2   map[string]any `json:"abcd"`
 
 	s []int `json:"-"`
 }
@@ -2087,7 +2087,7 @@ func TestUnmarshalJSONLiteralError(t *testing.T) {
 // Issue 3717
 func TestSkipArrayObjects(t *testing.T) {
 	json := `[{}]`
-	var dest [0]interface{}
+	var dest [0]any
 
 	err := Unmarshal([]byte(json), &dest)
 	if err != nil {
@@ -2102,8 +2102,8 @@ func TestPrefilled(t *testing.T) {
 	// Values here change, cannot reuse table across runs.
 	var prefillTests = []struct {
 		in  string
-		ptr interface{}
-		out interface{}
+		ptr any
+		out any
 	}{
 		{
 			in:  `{"X": 1, "Y": 2}`,
@@ -2112,8 +2112,8 @@ func TestPrefilled(t *testing.T) {
 		},
 		{
 			in:  `{"X": 1, "Y": 2}`,
-			ptr: &map[string]interface{}{"X": float32(3), "Y": int16(4), "Z": 1.5},
-			out: &map[string]interface{}{"X": float64(1), "Y": float64(2), "Z": 1.5},
+			ptr: &map[string]any{"X": float32(3), "Y": int16(4), "Z": 1.5},
+			out: &map[string]any{"X": float64(1), "Y": float64(2), "Z": 1.5},
 		},
 		{
 			in:  `[2]`,
@@ -2150,7 +2150,7 @@ func TestPrefilled(t *testing.T) {
 }
 
 var invalidUnmarshalTests = []struct {
-	v    interface{}
+	v    any
 	want string
 }{
 	{nil, "json: Unmarshal(nil)"},
@@ -2173,7 +2173,7 @@ func TestInvalidUnmarshal(t *testing.T) {
 }
 
 var invalidUnmarshalTextTests = []struct {
-	v    interface{}
+	v    any
 	want string
 }{
 	{nil, "json: Unmarshal(nil)"},
@@ -2205,7 +2205,7 @@ func TestInvalidStringOption(t *testing.T) {
 		M map[string]string `json:",string"`
 		S []string          `json:",string"`
 		A [1]string         `json:",string"`
-		I interface{}       `json:",string"`
+		I any               `json:",string"`
 		P *int              `json:",string"`
 	}{M: make(map[string]string), S: make([]string, 0), I: num, P: &num}
 
@@ -2276,8 +2276,8 @@ func TestUnmarshalEmbeddedUnexported(t *testing.T) {
 
 	tests := []struct {
 		in  string
-		ptr interface{}
-		out interface{}
+		ptr any
+		out any
 		err error
 	}{{
 		// Error since we cannot set S1.embed1, but still able to set S1.R.
@@ -2375,7 +2375,7 @@ func TestUnmarshalErrorAfterMultipleJSON(t *testing.T) {
 		dec := NewDecoder(strings.NewReader(tt.in))
 		var err error
 		for {
-			var v interface{}
+			var v any
 			if err = dec.Decode(&v); err != nil {
 				break
 			}
@@ -2403,7 +2403,7 @@ func TestUnmarshalPanic(t *testing.T) {
 // The decoder used to hang if decoding into an interface pointing to its own address.
 // See golang.org/issues/31740.
 func TestUnmarshalRecursivePointer(t *testing.T) {
-	var v interface{}
+	var v any
 	v = &v
 	data := []byte(`{"a": "b"}`)
 
@@ -2517,36 +2517,36 @@ func TestUnmarshalMaxDepth(t *testing.T) {
 
 	targets := []struct {
 		name     string
-		newValue func() interface{}
+		newValue func() any
 	}{
 		{
 			name: "unstructured",
-			newValue: func() interface{} {
-				var v interface{}
+			newValue: func() any {
+				var v any
 				return &v
 			},
 		},
 		{
 			name: "typed named field",
-			newValue: func() interface{} {
+			newValue: func() any {
 				v := struct {
-					A interface{} `json:"a"`
+					A any `json:"a"`
 				}{}
 				return &v
 			},
 		},
 		{
 			name: "typed missing field",
-			newValue: func() interface{} {
+			newValue: func() any {
 				v := struct {
-					B interface{} `json:"b"`
+					B any `json:"b"`
 				}{}
 				return &v
 			},
 		},
 		{
 			name: "custom unmarshaler",
-			newValue: func() interface{} {
+			newValue: func() any {
 				v := unmarshaler{}
 				return &v
 			},
diff --git a/internal/golang/encoding/json/encode.go b/internal/golang/encoding/json/encode.go
index e473e61..5b67251 100644
--- a/internal/golang/encoding/json/encode.go
+++ b/internal/golang/encoding/json/encode.go
@@ -77,31 +77,31 @@ import (
 //
 // Examples of struct field tags and their meanings:
 //
-//   // Field appears in JSON as key "myName".
-//   Field int `json:"myName"`
+//	// Field appears in JSON as key "myName".
+//	Field int `json:"myName"`
 //
-//   // Field appears in JSON as key "myName" and
-//   // the field is omitted from the object if its value is empty,
-//   // as defined above.
-//   Field int `json:"myName,omitempty"`
+//	// Field appears in JSON as key "myName" and
+//	// the field is omitted from the object if its value is empty,
+//	// as defined above.
+//	Field int `json:"myName,omitempty"`
 //
-//   // Field appears in JSON as key "Field" (the default), but
-//   // the field is skipped if empty.
-//   // Note the leading comma.
-//   Field int `json:",omitempty"`
+//	// Field appears in JSON as key "Field" (the default), but
+//	// the field is skipped if empty.
+//	// Note the leading comma.
+//	Field int `json:",omitempty"`
 //
-//   // Field is ignored by this package.
-//   Field int `json:"-"`
+//	// Field is ignored by this package.
+//	Field int `json:"-"`
 //
-//   // Field appears in JSON as key "-".
-//   Field int `json:"-,"`
+//	// Field appears in JSON as key "-".
+//	Field int `json:"-,"`
 //
 // The "string" option signals that a field is stored as JSON inside a
 // JSON-encoded string. It applies only to fields of string, floating point,
 // integer, or boolean types. This extra level of encoding is sometimes used
 // when communicating with JavaScript programs:
 //
-//    Int64String int64 `json:",string"`
+//	Int64String int64 `json:",string"`
 //
 // The key name will be used if it's a non-empty string consisting of
 // only Unicode letters, digits, and ASCII punctuation except quotation
@@ -154,8 +154,7 @@ import (
 // JSON cannot represent cyclic data structures and Marshal does not
 // handle them. Passing cyclic structures to Marshal will result in
 // an error.
-//
-func Marshal(v interface{}) ([]byte, error) {
+func Marshal(v any) ([]byte, error) {
 	e := newEncodeState()
 
 	err := e.marshal(v, encOpts{escapeHTML: true})
@@ -172,7 +171,7 @@ func Marshal(v interface{}) ([]byte, error) {
 // MarshalIndent is like Marshal but applies Indent to format the output.
 // Each JSON element in the output will begin on a new line beginning with prefix
 // followed by one or more copies of indent according to the indentation nesting.
-func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
+func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
 	b, err := Marshal(v)
 	if err != nil {
 		return nil, err
@@ -294,7 +293,7 @@ type encodeState struct {
 	// startDetectingCyclesAfter, so that we skip the work if we're within a
 	// reasonable amount of nested pointers deep.
 	ptrLevel uint
-	ptrSeen  map[interface{}]struct{}
+	ptrSeen  map[any]struct{}
 }
 
 const startDetectingCyclesAfter = 1000
@@ -311,7 +310,7 @@ func newEncodeState() *encodeState {
 		e.ptrLevel = 0
 		return e
 	}
-	return &encodeState{ptrSeen: make(map[interface{}]struct{})}
+	return &encodeState{ptrSeen: make(map[any]struct{})}
 }
 
 // jsonError is an error wrapper type for internal use only.
@@ -319,7 +318,7 @@ func newEncodeState() *encodeState {
 // can distinguish intentional panics from this package.
 type jsonError struct{ error }
 
-func (e *encodeState) marshal(v interface{}, opts encOpts) (err error) {
+func (e *encodeState) marshal(v any, opts encOpts) (err error) {
 	defer func() {
 		if r := recover(); r != nil {
 			if je, ok := r.(jsonError); ok {
@@ -350,7 +349,7 @@ func isEmptyValue(v reflect.Value) bool {
 		return v.Uint() == 0
 	case reflect.Float32, reflect.Float64:
 		return v.Float() == 0
-	case reflect.Interface, reflect.Ptr:
+	case reflect.Interface, reflect.Pointer:
 		return v.IsNil()
 	}
 	return false
@@ -419,13 +418,13 @@ func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
 	// Marshaler with a value receiver, then we're better off taking
 	// the address of the value - otherwise we end up with an
 	// allocation as we cast the value to an interface.
-	if t.Kind() != reflect.Ptr && allowAddr && reflect.PtrTo(t).Implements(marshalerType) {
+	if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(marshalerType) {
 		return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
 	}
 	if t.Implements(marshalerType) {
 		return marshalerEncoder
 	}
-	if t.Kind() != reflect.Ptr && allowAddr && reflect.PtrTo(t).Implements(textMarshalerType) {
+	if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(textMarshalerType) {
 		return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
 	}
 	if t.Implements(textMarshalerType) {
@@ -455,7 +454,7 @@ func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
 		return newSliceEncoder(t)
 	case reflect.Array:
 		return newArrayEncoder(t)
-	case reflect.Ptr:
+	case reflect.Pointer:
 		return newPtrEncoder(t)
 	default:
 		return unsupportedTypeEncoder
@@ -467,7 +466,7 @@ func invalidValueEncoder(e *encodeState, v reflect.Value, _ encOpts) {
 }
 
 func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
-	if v.Kind() == reflect.Ptr && v.IsNil() {
+	if v.Kind() == reflect.Pointer && v.IsNil() {
 		e.WriteString("null")
 		return
 	}
@@ -504,7 +503,7 @@ func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
 }
 
 func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
-	if v.Kind() == reflect.Ptr && v.IsNil() {
+	if v.Kind() == reflect.Pointer && v.IsNil() {
 		e.WriteString("null")
 		return
 	}
@@ -738,7 +737,7 @@ FieldLoop:
 		// Find the nested struct field by following f.index.
 		fv := v
 		for _, i := range f.index {
-			if fv.Kind() == reflect.Ptr {
+			if fv.Kind() == reflect.Pointer {
 				if fv.IsNil() {
 					continue FieldLoop
 				}
@@ -784,7 +783,7 @@ func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
 	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
 		// We're a large number of nested ptrEncoder.encode calls deep;
 		// start checking if we've run into a pointer cycle.
-		ptr := v.Pointer()
+		ptr := v.UnsafePointer()
 		if _, ok := e.ptrSeen[ptr]; ok {
 			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
 		}
@@ -877,9 +876,9 @@ func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
 		// Here we use a struct to memorize the pointer to the first element of the slice
 		// and its length.
 		ptr := struct {
-			ptr uintptr
+			ptr interface{} // always an unsafe.Pointer, but avoids a dependency on package unsafe
 			len int
-		}{v.Pointer(), v.Len()}
+		}{v.UnsafePointer(), v.Len()}
 		if _, ok := e.ptrSeen[ptr]; ok {
 			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
 		}
@@ -893,7 +892,7 @@ func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
 func newSliceEncoder(t reflect.Type) encoderFunc {
 	// Byte slices get special treatment; arrays don't.
 	if t.Elem().Kind() == reflect.Uint8 {
-		p := reflect.PtrTo(t.Elem())
+		p := reflect.PointerTo(t.Elem())
 		if !p.Implements(marshalerType) && !p.Implements(textMarshalerType) {
 			return encodeByteSlice
 		}
@@ -989,7 +988,7 @@ func isValidTag(s string) bool {
 
 func typeByIndex(t reflect.Type, index []int) reflect.Type {
 	for _, i := range index {
-		if t.Kind() == reflect.Ptr {
+		if t.Kind() == reflect.Pointer {
 			t = t.Elem()
 		}
 		t = t.Field(i).Type
@@ -1009,7 +1008,7 @@ func (w *reflectWithString) resolve() error {
 		return nil
 	}
 	if tm, ok := w.k.Interface().(encoding.TextMarshaler); ok {
-		if w.k.Kind() == reflect.Ptr && w.k.IsNil() {
+		if w.k.Kind() == reflect.Pointer && w.k.IsNil() {
 			return nil
 		}
 		buf, err := tm.MarshalText()
@@ -1243,7 +1242,7 @@ func typeFields(t reflect.Type) structFields {
 				sf := f.typ.Field(i)
 				if sf.Anonymous {
 					t := sf.Type
-					if t.Kind() == reflect.Ptr {
+					if t.Kind() == reflect.Pointer {
 						t = t.Elem()
 					}
 					if !sf.IsExported() && t.Kind() != reflect.Struct {
@@ -1269,7 +1268,7 @@ func typeFields(t reflect.Type) structFields {
 				index[len(f.index)] = i
 
 				ft := sf.Type
-				if ft.Name() == "" && ft.Kind() == reflect.Ptr {
+				if ft.Name() == "" && ft.Kind() == reflect.Pointer {
 					// Follow pointer.
 					ft = ft.Elem()
 				}
diff --git a/internal/golang/encoding/json/encode_test.go b/internal/golang/encoding/json/encode_test.go
index 0dad951..0b021f0 100644
--- a/internal/golang/encoding/json/encode_test.go
+++ b/internal/golang/encoding/json/encode_test.go
@@ -28,8 +28,8 @@ type Optionals struct {
 	Slr []string `json:"slr,random"`
 	Slo []string `json:"slo,omitempty"`
 
-	Mr map[string]interface{} `json:"mr"`
-	Mo map[string]interface{} `json:",omitempty"`
+	Mr map[string]any `json:"mr"`
+	Mo map[string]any `json:",omitempty"`
 
 	Fr float64 `json:"fr"`
 	Fo float64 `json:"fo,omitempty"`
@@ -59,8 +59,8 @@ var optionalsExpected = `{
 func TestOmitEmpty(t *testing.T) {
 	var o Optionals
 	o.Sw = "something"
-	o.Mr = map[string]interface{}{}
-	o.Mo = map[string]interface{}{}
+	o.Mr = map[string]any{}
+	o.Mo = map[string]any{}
 
 	got, err := MarshalIndent(&o, "", " ")
 	if err != nil {
@@ -180,16 +180,16 @@ type PointerCycle struct {
 var pointerCycle = &PointerCycle{}
 
 type PointerCycleIndirect struct {
-	Ptrs []interface{}
+	Ptrs []any
 }
 
 type RecursiveSlice []RecursiveSlice
 
 var (
 	pointerCycleIndirect = &PointerCycleIndirect{}
-	mapCycle             = make(map[string]interface{})
-	sliceCycle           = []interface{}{nil}
-	sliceNoCycle         = []interface{}{nil, nil}
+	mapCycle             = make(map[string]any)
+	sliceCycle           = []any{nil}
+	sliceNoCycle         = []any{nil, nil}
 	recursiveSliceCycle  = []RecursiveSlice{nil}
 )
 
@@ -199,13 +199,13 @@ func init() {
 	samePointerNoCycle.Ptr2 = ptr
 
 	pointerCycle.Ptr = pointerCycle
-	pointerCycleIndirect.Ptrs = []interface{}{pointerCycleIndirect}
+	pointerCycleIndirect.Ptrs = []any{pointerCycleIndirect}
 
 	mapCycle["x"] = mapCycle
 	sliceCycle[0] = sliceCycle
 	sliceNoCycle[1] = sliceNoCycle[:1]
 	for i := startDetectingCyclesAfter; i > 0; i-- {
-		sliceNoCycle = []interface{}{sliceNoCycle}
+		sliceNoCycle = []any{sliceNoCycle}
 	}
 	recursiveSliceCycle[0] = recursiveSliceCycle
 }
@@ -222,7 +222,7 @@ func TestSliceNoCycle(t *testing.T) {
 	}
 }
 
-var unsupportedValues = []interface{}{
+var unsupportedValues = []any{
 	math.NaN(),
 	math.Inf(-1),
 	math.Inf(1),
@@ -367,15 +367,15 @@ func TestMarshalerEscaping(t *testing.T) {
 
 func TestAnonymousFields(t *testing.T) {
 	tests := []struct {
-		label     string             // Test name
-		makeInput func() interface{} // Function to create input value
-		want      string             // Expected JSON output
+		label     string     // Test name
+		makeInput func() any // Function to create input value
+		want      string     // Expected JSON output
 	}{{
 		// Both S1 and S2 have a field named X. From the perspective of S,
 		// it is ambiguous which one X refers to.
 		// This should not serialize either field.
 		label: "AmbiguousField",
-		makeInput: func() interface{} {
+		makeInput: func() any {
 			type (
 				S1 struct{ x, X int }
 				S2 struct{ x, X int }
@@ -391,7 +391,7 @@ func TestAnonymousFields(t *testing.T) {
 		label: "DominantField",
 		// Both S1 and S2 have a field named X, but since S has an X field as
 		// well, it takes precedence over S1.X and S2.X.
-		makeInput: func() interface{} {
+		makeInput: func() any {
 			type (
 				S1 struct{ x, X int }
 				S2 struct{ x, X int }
@@ -407,7 +407,7 @@ func TestAnonymousFields(t *testing.T) {
 	}, {
 		// Unexported embedded field of non-struct type should not be serialized.
 		label: "UnexportedEmbeddedInt",
-		makeInput: func() interface{} {
+		makeInput: func() any {
 			type (
 				myInt int
 				S     struct{ myInt }
@@ -418,7 +418,7 @@ func TestAnonymousFields(t *testing.T) {
 	}, {
 		// Exported embedded field of non-struct type should be serialized.
 		label: "ExportedEmbeddedInt",
-		makeInput: func() interface{} {
+		makeInput: func() any {
 			type (
 				MyInt int
 				S     struct{ MyInt }
@@ -430,7 +430,7 @@ func TestAnonymousFields(t *testing.T) {
 		// Unexported embedded field of pointer to non-struct type
 		// should not be serialized.
 		label: "UnexportedEmbeddedIntPointer",
-		makeInput: func() interface{} {
+		makeInput: func() any {
 			type (
 				myInt int
 				S     struct{ *myInt }
@@ -444,7 +444,7 @@ func TestAnonymousFields(t *testing.T) {
 		// Exported embedded field of pointer to non-struct type
 		// should be serialized.
 		label: "ExportedEmbeddedIntPointer",
-		makeInput: func() interface{} {
+		makeInput: func() any {
 			type (
 				MyInt int
 				S     struct{ *MyInt }
@@ -459,7 +459,7 @@ func TestAnonymousFields(t *testing.T) {
 		// exported fields be serialized regardless of whether the struct types
 		// themselves are exported.
 		label: "EmbeddedStruct",
-		makeInput: func() interface{} {
+		makeInput: func() any {
 			type (
 				s1 struct{ x, X int }
 				S2 struct{ y, Y int }
@@ -476,7 +476,7 @@ func TestAnonymousFields(t *testing.T) {
 		// exported fields be serialized regardless of whether the struct types
 		// themselves are exported.
 		label: "EmbeddedStructPointer",
-		makeInput: func() interface{} {
+		makeInput: func() any {
 			type (
 				s1 struct{ x, X int }
 				S2 struct{ y, Y int }
@@ -492,7 +492,7 @@ func TestAnonymousFields(t *testing.T) {
 		// Exported fields on embedded unexported structs at multiple levels
 		// of nesting should still be serialized.
 		label: "NestedStructAndInts",
-		makeInput: func() interface{} {
+		makeInput: func() any {
 			type (
 				MyInt1 int
 				MyInt2 int
@@ -519,7 +519,7 @@ func TestAnonymousFields(t *testing.T) {
 		// the embedded fields behind it. Not properly doing so may
 		// result in the wrong output or reflect panics.
 		label: "EmbeddedFieldBehindNilPointer",
-		makeInput: func() interface{} {
+		makeInput: func() any {
 			type (
 				S2 struct{ Field string }
 				S  struct{ *S2 }
@@ -589,22 +589,22 @@ func (nm *nilTextMarshaler) MarshalText() ([]byte, error) {
 // See golang.org/issue/16042 and golang.org/issue/34235.
 func TestNilMarshal(t *testing.T) {
 	testCases := []struct {
-		v    interface{}
+		v    any
 		want string
 	}{
 		{v: nil, want: `null`},
 		{v: new(float64), want: `0`},
-		{v: []interface{}(nil), want: `null`},
+		{v: []any(nil), want: `null`},
 		{v: []string(nil), want: `null`},
 		{v: map[string]string(nil), want: `null`},
 		{v: []byte(nil), want: `null`},
 		{v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`},
 		{v: struct{ M Marshaler }{}, want: `{"M":null}`},
 		{v: struct{ M Marshaler }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
-		{v: struct{ M interface{} }{(*nilJSONMarshaler)(nil)}, want: `{"M":null}`},
+		{v: struct{ M any }{(*nilJSONMarshaler)(nil)}, want: `{"M":null}`},
 		{v: struct{ M encoding.TextMarshaler }{}, want: `{"M":null}`},
 		{v: struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
-		{v: struct{ M interface{} }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`},
+		{v: struct{ M any }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`},
 	}
 
 	for _, tt := range testCases {
@@ -864,7 +864,7 @@ type textint int
 
 func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) }
 
-func tenc(format string, a ...interface{}) ([]byte, error) {
+func tenc(format string, a ...any) ([]byte, error) {
 	var buf bytes.Buffer
 	fmt.Fprintf(&buf, format, a...)
 	return buf.Bytes(), nil
@@ -877,7 +877,7 @@ func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) }
 // Issue 13783
 func TestEncodeBytekind(t *testing.T) {
 	testdata := []struct {
-		data interface{}
+		data any
 		want string
 	}{
 		{byte(7), "7"},
@@ -966,7 +966,7 @@ func TestMarshalFloat(t *testing.T) {
 	t.Parallel()
 	nfail := 0
 	test := func(f float64, bits int) {
-		vf := interface{}(f)
+		vf := any(f)
 		if bits == 32 {
 			f = float64(float32(f)) // round
 			vf = float32(f)
@@ -1062,25 +1062,25 @@ func TestMarshalRawMessageValue(t *testing.T) {
 	)
 
 	tests := []struct {
-		in   interface{}
+		in   any
 		want string
 		ok   bool
 	}{
 		// Test with nil RawMessage.
 		{rawNil, "null", true},
 		{&rawNil, "null", true},
-		{[]interface{}{rawNil}, "[null]", true},
-		{&[]interface{}{rawNil}, "[null]", true},
-		{[]interface{}{&rawNil}, "[null]", true},
-		{&[]interface{}{&rawNil}, "[null]", true},
+		{[]any{rawNil}, "[null]", true},
+		{&[]any{rawNil}, "[null]", true},
+		{[]any{&rawNil}, "[null]", true},
+		{&[]any{&rawNil}, "[null]", true},
 		{struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
 		{&struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
 		{struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
 		{&struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
-		{map[string]interface{}{"M": rawNil}, `{"M":null}`, true},
-		{&map[string]interface{}{"M": rawNil}, `{"M":null}`, true},
-		{map[string]interface{}{"M": &rawNil}, `{"M":null}`, true},
-		{&map[string]interface{}{"M": &rawNil}, `{"M":null}`, true},
+		{map[string]any{"M": rawNil}, `{"M":null}`, true},
+		{&map[string]any{"M": rawNil}, `{"M":null}`, true},
+		{map[string]any{"M": &rawNil}, `{"M":null}`, true},
+		{&map[string]any{"M": &rawNil}, `{"M":null}`, true},
 		{T1{rawNil}, "{}", true},
 		{T2{&rawNil}, `{"M":null}`, true},
 		{&T1{rawNil}, "{}", true},
@@ -1089,18 +1089,18 @@ func TestMarshalRawMessageValue(t *testing.T) {
 		// Test with empty, but non-nil, RawMessage.
 		{rawEmpty, "", false},
 		{&rawEmpty, "", false},
-		{[]interface{}{rawEmpty}, "", false},
-		{&[]interface{}{rawEmpty}, "", false},
-		{[]interface{}{&rawEmpty}, "", false},
-		{&[]interface{}{&rawEmpty}, "", false},
+		{[]any{rawEmpty}, "", false},
+		{&[]any{rawEmpty}, "", false},
+		{[]any{&rawEmpty}, "", false},
+		{&[]any{&rawEmpty}, "", false},
 		{struct{ X RawMessage }{rawEmpty}, "", false},
 		{&struct{ X RawMessage }{rawEmpty}, "", false},
 		{struct{ X *RawMessage }{&rawEmpty}, "", false},
 		{&struct{ X *RawMessage }{&rawEmpty}, "", false},
-		{map[string]interface{}{"nil": rawEmpty}, "", false},
-		{&map[string]interface{}{"nil": rawEmpty}, "", false},
-		{map[string]interface{}{"nil": &rawEmpty}, "", false},
-		{&map[string]interface{}{"nil": &rawEmpty}, "", false},
+		{map[string]any{"nil": rawEmpty}, "", false},
+		{&map[string]any{"nil": rawEmpty}, "", false},
+		{map[string]any{"nil": &rawEmpty}, "", false},
+		{&map[string]any{"nil": &rawEmpty}, "", false},
 		{T1{rawEmpty}, "{}", true},
 		{T2{&rawEmpty}, "", false},
 		{&T1{rawEmpty}, "{}", true},
@@ -1113,18 +1113,18 @@ func TestMarshalRawMessageValue(t *testing.T) {
 		// See https://golang.org/issues/14493#issuecomment-255857318
 		{rawText, `"foo"`, true}, // Issue6458
 		{&rawText, `"foo"`, true},
-		{[]interface{}{rawText}, `["foo"]`, true},  // Issue6458
-		{&[]interface{}{rawText}, `["foo"]`, true}, // Issue6458
-		{[]interface{}{&rawText}, `["foo"]`, true},
-		{&[]interface{}{&rawText}, `["foo"]`, true},
+		{[]any{rawText}, `["foo"]`, true},  // Issue6458
+		{&[]any{rawText}, `["foo"]`, true}, // Issue6458
+		{[]any{&rawText}, `["foo"]`, true},
+		{&[]any{&rawText}, `["foo"]`, true},
 		{struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true}, // Issue6458
 		{&struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true},
 		{struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
 		{&struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
-		{map[string]interface{}{"M": rawText}, `{"M":"foo"}`, true},  // Issue6458
-		{&map[string]interface{}{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458
-		{map[string]interface{}{"M": &rawText}, `{"M":"foo"}`, true},
-		{&map[string]interface{}{"M": &rawText}, `{"M":"foo"}`, true},
+		{map[string]any{"M": rawText}, `{"M":"foo"}`, true},  // Issue6458
+		{&map[string]any{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458
+		{map[string]any{"M": &rawText}, `{"M":"foo"}`, true},
+		{&map[string]any{"M": &rawText}, `{"M":"foo"}`, true},
 		{T1{rawText}, `{"M":"foo"}`, true}, // Issue6458
 		{T2{&rawText}, `{"M":"foo"}`, true},
 		{&T1{rawText}, `{"M":"foo"}`, true},
diff --git a/internal/golang/encoding/json/example_test.go b/internal/golang/encoding/json/example_test.go
index fbecf1b..2261c77 100644
--- a/internal/golang/encoding/json/example_test.go
+++ b/internal/golang/encoding/json/example_test.go
@@ -200,7 +200,7 @@ func ExampleRawMessage_unmarshal() {
 	}
 
 	for _, c := range colors {
-		var dst interface{}
+		var dst any
 		switch c.Space {
 		case "RGB":
 			dst = new(RGB)
diff --git a/internal/golang/encoding/json/fold.go b/internal/golang/encoding/json/fold.go
index 9e17012..ab249b2 100644
--- a/internal/golang/encoding/json/fold.go
+++ b/internal/golang/encoding/json/fold.go
@@ -24,8 +24,9 @@ const (
 // 4) simpleLetterEqualFold, no specials, no non-letters.
 //
 // The letters S and K are special because they map to 3 runes, not just 2:
-//  * S maps to s and to U+017F 'ſ' Latin small letter long s
-//  * k maps to K and to U+212A 'K' Kelvin sign
+//   - S maps to s and to U+017F 'ſ' Latin small letter long s
+//   - k maps to K and to U+212A 'K' Kelvin sign
+//
 // See https://play.golang.org/p/tTxjOc0OGo
 //
 // The returned function is specialized for matching against s and
diff --git a/internal/golang/encoding/json/fuzz.go b/internal/golang/encoding/json/fuzz.go
index d3fa2d1..b8f4ff2 100644
--- a/internal/golang/encoding/json/fuzz.go
+++ b/internal/golang/encoding/json/fuzz.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build gofuzz
-// +build gofuzz
 
 package json
 
@@ -12,10 +11,10 @@ import (
 )
 
 func Fuzz(data []byte) (score int) {
-	for _, ctor := range []func() interface{}{
-		func() interface{} { return new(interface{}) },
-		func() interface{} { return new(map[string]interface{}) },
-		func() interface{} { return new([]interface{}) },
+	for _, ctor := range []func() any{
+		func() any { return new(any) },
+		func() any { return new(map[string]any) },
+		func() any { return new([]any) },
 	} {
 		v := ctor()
 		err := Unmarshal(data, v)
diff --git a/internal/golang/encoding/json/fuzz_test.go b/internal/golang/encoding/json/fuzz_test.go
new file mode 100644
index 0000000..778664c
--- /dev/null
+++ b/internal/golang/encoding/json/fuzz_test.go
@@ -0,0 +1,83 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package json
+
+import (
+	"bytes"
+	"io"
+	"testing"
+)
+
+func FuzzUnmarshalJSON(f *testing.F) {
+	f.Add([]byte(`{
+"object": {
+	"slice": [
+		1,
+		2.0,
+		"3",
+		[4],
+		{5: {}}
+	]
+},
+"slice": [[]],
+"string": ":)",
+"int": 1e5,
+"float": 3e-9"
+}`))
+
+	f.Fuzz(func(t *testing.T, b []byte) {
+		for _, typ := range []func() interface{}{
+			func() interface{} { return new(interface{}) },
+			func() interface{} { return new(map[string]interface{}) },
+			func() interface{} { return new([]interface{}) },
+		} {
+			i := typ()
+			if err := Unmarshal(b, i); err != nil {
+				return
+			}
+
+			encoded, err := Marshal(i)
+			if err != nil {
+				t.Fatalf("failed to marshal: %s", err)
+			}
+
+			if err := Unmarshal(encoded, i); err != nil {
+				t.Fatalf("failed to roundtrip: %s", err)
+			}
+		}
+	})
+}
+
+func FuzzDecoderToken(f *testing.F) {
+	f.Add([]byte(`{
+"object": {
+	"slice": [
+		1,
+		2.0,
+		"3",
+		[4],
+		{5: {}}
+	]
+},
+"slice": [[]],
+"string": ":)",
+"int": 1e5,
+"float": 3e-9"
+}`))
+
+	f.Fuzz(func(t *testing.T, b []byte) {
+		r := bytes.NewReader(b)
+		d := NewDecoder(r)
+		for {
+			_, err := d.Token()
+			if err != nil {
+				if err == io.EOF {
+					break
+				}
+				return
+			}
+		}
+	})
+}
diff --git a/internal/golang/encoding/json/kubernetes_patch.go b/internal/golang/encoding/json/kubernetes_patch.go
index cb9ab06..e1c0a74 100644
--- a/internal/golang/encoding/json/kubernetes_patch.go
+++ b/internal/golang/encoding/json/kubernetes_patch.go
@@ -18,7 +18,6 @@ package json
 
 import (
 	gojson "encoding/json"
-	"fmt"
 	"strconv"
 	"strings"
 )
@@ -71,32 +70,37 @@ func (d *Decoder) DisallowDuplicateFields() {
 	d.d.disallowDuplicateFields = true
 }
 
-func (d *decodeState) newFieldError(msg, field string) error {
+func (d *decodeState) newFieldError(errType strictErrType, field string) *strictError {
 	if len(d.strictFieldStack) > 0 {
-		return fmt.Errorf("%s %q", msg, strings.Join(d.strictFieldStack, "")+"."+field)
+		return &strictError{
+			ErrType: errType,
+			Path:    strings.Join(d.strictFieldStack, "") + "." + field,
+		}
 	} else {
-		return fmt.Errorf("%s %q", msg, field)
+		return &strictError{
+			ErrType: errType,
+			Path:    field,
+		}
 	}
 }
 
 // saveStrictError saves a strict decoding error,
 // for reporting at the end of the unmarshal if no other errors occurred.
-func (d *decodeState) saveStrictError(err error) {
+func (d *decodeState) saveStrictError(err *strictError) {
 	// prevent excessive numbers of accumulated errors
 	if len(d.savedStrictErrors) >= 100 {
 		return
 	}
 	// dedupe accumulated strict errors
 	if d.seenStrictErrors == nil {
-		d.seenStrictErrors = map[string]struct{}{}
+		d.seenStrictErrors = map[strictError]struct{}{}
 	}
-	msg := err.Error()
-	if _, seen := d.seenStrictErrors[msg]; seen {
+	if _, seen := d.seenStrictErrors[*err]; seen {
 		return
 	}
 
 	// accumulate the error
-	d.seenStrictErrors[msg] = struct{}{}
+	d.seenStrictErrors[*err] = struct{}{}
 	d.savedStrictErrors = append(d.savedStrictErrors, err)
 }
 
@@ -118,6 +122,33 @@ func (d *decodeState) appendStrictFieldStackIndex(i int) {
 	d.strictFieldStack = append(d.strictFieldStack, "[", strconv.Itoa(i), "]")
 }
 
+type strictErrType string
+
+const (
+	unknownStrictErrType   strictErrType = "unknown field"
+	duplicateStrictErrType strictErrType = "duplicate field"
+)
+
+// strictError is a strict decoding error
+// It has an ErrType (either unknown or duplicate)
+// and a path to the erroneous field
+type strictError struct {
+	ErrType strictErrType
+	Path    string
+}
+
+func (e *strictError) Error() string {
+	return string(e.ErrType) + " " + strconv.Quote(e.Path)
+}
+
+func (e *strictError) FieldPath() string {
+	return e.Path
+}
+
+func (e *strictError) SetFieldPath(path string) {
+	e.Path = path
+}
+
 // UnmarshalStrictError holds errors resulting from use of strict disallow___ decoder directives.
 // If this is returned from Unmarshal(), it means the decoding was successful in all other respects.
 type UnmarshalStrictError struct {
diff --git a/internal/golang/encoding/json/scanner.go b/internal/golang/encoding/json/scanner.go
index 9dc1903..22fc692 100644
--- a/internal/golang/encoding/json/scanner.go
+++ b/internal/golang/encoding/json/scanner.go
@@ -27,6 +27,7 @@ func Valid(data []byte) bool {
 
 // checkValid verifies that data is valid JSON-encoded data.
 // scan is passed in for use by checkValid to avoid an allocation.
+// checkValid returns nil or a SyntaxError.
 func checkValid(data []byte, scan *scanner) error {
 	scan.reset()
 	for _, c := range data {
@@ -42,6 +43,7 @@ func checkValid(data []byte, scan *scanner) error {
 }
 
 // A SyntaxError is a description of a JSON syntax error.
+// Unmarshal will return a SyntaxError if the JSON can't be parsed.
 type SyntaxError struct {
 	msg    string // description of error
 	Offset int64  // error occurred after reading Offset bytes
@@ -83,7 +85,7 @@ type scanner struct {
 }
 
 var scannerPool = sync.Pool{
-	New: func() interface{} {
+	New: func() any {
 		return &scanner{}
 	},
 }
diff --git a/internal/golang/encoding/json/scanner_test.go b/internal/golang/encoding/json/scanner_test.go
index 3737516..3474b3e 100644
--- a/internal/golang/encoding/json/scanner_test.go
+++ b/internal/golang/encoding/json/scanner_test.go
@@ -237,7 +237,7 @@ func initBig() {
 	jsonBig = b
 }
 
-func genValue(n int) interface{} {
+func genValue(n int) any {
 	if n > 1 {
 		switch rand.Intn(2) {
 		case 0:
@@ -270,7 +270,7 @@ func genString(stddev float64) string {
 	return string(c)
 }
 
-func genArray(n int) []interface{} {
+func genArray(n int) []any {
 	f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2)))
 	if f > n {
 		f = n
@@ -278,14 +278,14 @@ func genArray(n int) []interface{} {
 	if f < 1 {
 		f = 1
 	}
-	x := make([]interface{}, f)
+	x := make([]any, f)
 	for i := range x {
 		x[i] = genValue(((i+1)*n)/f - (i*n)/f)
 	}
 	return x
 }
 
-func genMap(n int) map[string]interface{} {
+func genMap(n int) map[string]any {
 	f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2)))
 	if f > n {
 		f = n
@@ -293,7 +293,7 @@ func genMap(n int) map[string]interface{} {
 	if n > 0 && f == 0 {
 		f = 1
 	}
-	x := make(map[string]interface{})
+	x := make(map[string]any)
 	for i := 0; i < f; i++ {
 		x[genString(10)] = genValue(((i+1)*n)/f - (i*n)/f)
 	}
diff --git a/internal/golang/encoding/json/stream.go b/internal/golang/encoding/json/stream.go
index 5f87df1..1967755 100644
--- a/internal/golang/encoding/json/stream.go
+++ b/internal/golang/encoding/json/stream.go
@@ -45,7 +45,7 @@ func (dec *Decoder) DisallowUnknownFields() { dec.d.disallowUnknownFields = true
 //
 // See the documentation for Unmarshal for details about
 // the conversion of JSON into a Go value.
-func (dec *Decoder) Decode(v interface{}) error {
+func (dec *Decoder) Decode(v any) error {
 	if dec.err != nil {
 		return dec.err
 	}
@@ -197,7 +197,7 @@ func NewEncoder(w io.Writer) *Encoder {
 //
 // See the documentation for Marshal for details about the
 // conversion of Go values to JSON.
-func (enc *Encoder) Encode(v interface{}) error {
+func (enc *Encoder) Encode(v any) error {
 	if enc.err != nil {
 		return enc.err
 	}
@@ -289,8 +289,7 @@ var _ Unmarshaler = (*RawMessage)(nil)
 //	Number, for JSON numbers
 //	string, for JSON string literals
 //	nil, for JSON null
-//
-type Token interface{}
+type Token any
 */
 
 const (
@@ -457,7 +456,7 @@ func (dec *Decoder) Token() (Token, error) {
 			if !dec.tokenValueAllowed() {
 				return dec.tokenError(c)
 			}
-			var x interface{}
+			var x any
 			if err := dec.Decode(&x); err != nil {
 				return nil, err
 			}
diff --git a/internal/golang/encoding/json/stream_test.go b/internal/golang/encoding/json/stream_test.go
index c284f2d..0e156d9 100644
--- a/internal/golang/encoding/json/stream_test.go
+++ b/internal/golang/encoding/json/stream_test.go
@@ -18,14 +18,14 @@ import (
 
 // Test values for the stream test.
 // One of each JSON kind.
-var streamTest = []interface{}{
+var streamTest = []any{
 	0.1,
 	"hello",
 	nil,
 	true,
 	false,
-	[]interface{}{"a", "b", "c"},
-	map[string]interface{}{"K": "Kelvin", "ß": "long s"},
+	[]any{"a", "b", "c"},
+	map[string]any{"K": "Kelvin", "ß": "long s"},
 	3.14, // another value to make sure something can follow map
 }
 
@@ -124,7 +124,7 @@ func TestEncoderSetEscapeHTML(t *testing.T) {
 
 	for _, tt := range []struct {
 		name       string
-		v          interface{}
+		v          any
 		wantEscape string
 		want       string
 	}{
@@ -182,7 +182,7 @@ func TestDecoder(t *testing.T) {
 				buf.WriteRune(c)
 			}
 		}
-		out := make([]interface{}, i)
+		out := make([]any, i)
 		dec := NewDecoder(&buf)
 		for j := range out {
 			if err := dec.Decode(&out[j]); err != nil {
@@ -297,7 +297,7 @@ func TestBlocking(t *testing.T) {
 	for _, enc := range blockingTests {
 		r, w := net.Pipe()
 		go w.Write([]byte(enc))
-		var val interface{}
+		var val any
 
 		// If Decode reads beyond what w.Write writes above,
 		// it will block, and the test will deadlock.
@@ -326,80 +326,80 @@ func BenchmarkEncoderEncode(b *testing.B) {
 
 type tokenStreamCase struct {
 	json      string
-	expTokens []interface{}
+	expTokens []any
 }
 
 type decodeThis struct {
-	v interface{}
+	v any
 }
 
 var tokenStreamCases = []tokenStreamCase{
 	// streaming token cases
-	{json: `10`, expTokens: []interface{}{float64(10)}},
-	{json: ` [10] `, expTokens: []interface{}{
+	{json: `10`, expTokens: []any{float64(10)}},
+	{json: ` [10] `, expTokens: []any{
 		Delim('['), float64(10), Delim(']')}},
-	{json: ` [false,10,"b"] `, expTokens: []interface{}{
+	{json: ` [false,10,"b"] `, expTokens: []any{
 		Delim('['), false, float64(10), "b", Delim(']')}},
-	{json: `{ "a": 1 }`, expTokens: []interface{}{
+	{json: `{ "a": 1 }`, expTokens: []any{
 		Delim('{'), "a", float64(1), Delim('}')}},
-	{json: `{"a": 1, "b":"3"}`, expTokens: []interface{}{
+	{json: `{"a": 1, "b":"3"}`, expTokens: []any{
 		Delim('{'), "a", float64(1), "b", "3", Delim('}')}},
-	{json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{
+	{json: ` [{"a": 1},{"a": 2}] `, expTokens: []any{
 		Delim('['),
 		Delim('{'), "a", float64(1), Delim('}'),
 		Delim('{'), "a", float64(2), Delim('}'),
 		Delim(']')}},
-	{json: `{"obj": {"a": 1}}`, expTokens: []interface{}{
+	{json: `{"obj": {"a": 1}}`, expTokens: []any{
 		Delim('{'), "obj", Delim('{'), "a", float64(1), Delim('}'),
 		Delim('}')}},
-	{json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{
+	{json: `{"obj": [{"a": 1}]}`, expTokens: []any{
 		Delim('{'), "obj", Delim('['),
 		Delim('{'), "a", float64(1), Delim('}'),
 		Delim(']'), Delim('}')}},
 
 	// streaming tokens with intermittent Decode()
-	{json: `{ "a": 1 }`, expTokens: []interface{}{
+	{json: `{ "a": 1 }`, expTokens: []any{
 		Delim('{'), "a",
 		decodeThis{float64(1)},
 		Delim('}')}},
-	{json: ` [ { "a" : 1 } ] `, expTokens: []interface{}{
+	{json: ` [ { "a" : 1 } ] `, expTokens: []any{
 		Delim('['),
-		decodeThis{map[string]interface{}{"a": float64(1)}},
+		decodeThis{map[string]any{"a": float64(1)}},
 		Delim(']')}},
-	{json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{
+	{json: ` [{"a": 1},{"a": 2}] `, expTokens: []any{
 		Delim('['),
-		decodeThis{map[string]interface{}{"a": float64(1)}},
-		decodeThis{map[string]interface{}{"a": float64(2)}},
+		decodeThis{map[string]any{"a": float64(1)}},
+		decodeThis{map[string]any{"a": float64(2)}},
 		Delim(']')}},
-	{json: `{ "obj" : [ { "a" : 1 } ] }`, expTokens: []interface{}{
+	{json: `{ "obj" : [ { "a" : 1 } ] }`, expTokens: []any{
 		Delim('{'), "obj", Delim('['),
-		decodeThis{map[string]interface{}{"a": float64(1)}},
+		decodeThis{map[string]any{"a": float64(1)}},
 		Delim(']'), Delim('}')}},
 
-	{json: `{"obj": {"a": 1}}`, expTokens: []interface{}{
+	{json: `{"obj": {"a": 1}}`, expTokens: []any{
 		Delim('{'), "obj",
-		decodeThis{map[string]interface{}{"a": float64(1)}},
+		decodeThis{map[string]any{"a": float64(1)}},
 		Delim('}')}},
-	{json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{
+	{json: `{"obj": [{"a": 1}]}`, expTokens: []any{
 		Delim('{'), "obj",
-		decodeThis{[]interface{}{
-			map[string]interface{}{"a": float64(1)},
+		decodeThis{[]any{
+			map[string]any{"a": float64(1)},
 		}},
 		Delim('}')}},
-	{json: ` [{"a": 1} {"a": 2}] `, expTokens: []interface{}{
+	{json: ` [{"a": 1} {"a": 2}] `, expTokens: []any{
 		Delim('['),
-		decodeThis{map[string]interface{}{"a": float64(1)}},
+		decodeThis{map[string]any{"a": float64(1)}},
 		decodeThis{&SyntaxError{"expected comma after array element", 11}},
 	}},
-	{json: `{ "` + strings.Repeat("a", 513) + `" 1 }`, expTokens: []interface{}{
+	{json: `{ "` + strings.Repeat("a", 513) + `" 1 }`, expTokens: []any{
 		Delim('{'), strings.Repeat("a", 513),
 		decodeThis{&SyntaxError{"expected colon after object key", 518}},
 	}},
-	{json: `{ "\a" }`, expTokens: []interface{}{
+	{json: `{ "\a" }`, expTokens: []any{
 		Delim('{'),
 		&SyntaxError{"invalid character 'a' in string escape code", 3},
 	}},
-	{json: ` \a`, expTokens: []interface{}{
+	{json: ` \a`, expTokens: []any{
 		&SyntaxError{"invalid character '\\\\' looking for beginning of value", 1},
 	}},
 }
@@ -410,7 +410,7 @@ func TestDecodeInStream(t *testing.T) {
 		dec := NewDecoder(strings.NewReader(tcase.json))
 		for i, etk := range tcase.expTokens {
 
-			var tk interface{}
+			var tk any
 			var err error
 
 			if dt, ok := etk.(decodeThis); ok {
diff --git a/internal/golang/encoding/json/tagkey_test.go b/internal/golang/encoding/json/tagkey_test.go
index bbb4e6a..6330efd 100644
--- a/internal/golang/encoding/json/tagkey_test.go
+++ b/internal/golang/encoding/json/tagkey_test.go
@@ -73,7 +73,7 @@ type unicodeTag struct {
 }
 
 var structTagObjectKeyTests = []struct {
-	raw   interface{}
+	raw   any
 	value string
 	key   string
 }{
@@ -101,12 +101,12 @@ func TestStructTagObjectKey(t *testing.T) {
 		if err != nil {
 			t.Fatalf("Marshal(%#q) failed: %v", tt.raw, err)
 		}
-		var f interface{}
+		var f any
 		err = Unmarshal(b, &f)
 		if err != nil {
 			t.Fatalf("Unmarshal(%#q) failed: %v", b, err)
 		}
-		for i, v := range f.(map[string]interface{}) {
+		for i, v := range f.(map[string]any) {
 			switch i {
 			case tt.key:
 				if s, ok := v.(string); !ok || s != tt.value {
diff --git a/internal/golang/encoding/json/tags.go b/internal/golang/encoding/json/tags.go
index c38fd51..b490328 100644
--- a/internal/golang/encoding/json/tags.go
+++ b/internal/golang/encoding/json/tags.go
@@ -15,10 +15,8 @@ type tagOptions string
 // parseTag splits a struct field's json tag into its name and
 // comma-separated options.
 func parseTag(tag string) (string, tagOptions) {
-	if idx := strings.Index(tag, ","); idx != -1 {
-		return tag[:idx], tagOptions(tag[idx+1:])
-	}
-	return tag, tagOptions("")
+	tag, opt, _ := strings.Cut(tag, ",")
+	return tag, tagOptions(opt)
 }
 
 // Contains reports whether a comma-separated list of options
@@ -30,15 +28,11 @@ func (o tagOptions) Contains(optionName string) bool {
 	}
 	s := string(o)
 	for s != "" {
-		var next string
-		i := strings.Index(s, ",")
-		if i >= 0 {
-			s, next = s[:i], s[i+1:]
-		}
-		if s == optionName {
+		var name string
+		name, s, _ = strings.Cut(s, ",")
+		if name == optionName {
 			return true
 		}
-		s = next
 	}
 	return false
 }
diff --git a/json.go b/json.go
index 764e2a8..e8f31b1 100644
--- a/json.go
+++ b/json.go
@@ -34,13 +34,13 @@ type Decoder interface {
 }
 
 // NewDecoderCaseSensitivePreserveInts returns a decoder that matches the behavior of encoding/json#NewDecoder, with the following changes:
-// - When unmarshaling into a struct, JSON keys must case-sensitively match `json` tag names (for tagged struct fields)
-//   or struct field names (for untagged struct fields), or they are treated as unknown fields and discarded.
-// - When unmarshaling a number into an interface value, it is unmarshaled as an int64 if
-//   the JSON data does not contain a "." character and parses as an integer successfully and
-//   does not overflow int64. Otherwise, the number is unmarshaled as a float64.
-// - If a syntax error is returned, it will not be of type encoding/json#SyntaxError,
-//   but will be recognizeable by this package's IsSyntaxError() function.
+//   - When unmarshaling into a struct, JSON keys must case-sensitively match `json` tag names (for tagged struct fields)
+//     or struct field names (for untagged struct fields), or they are treated as unknown fields and discarded.
+//   - When unmarshaling a number into an interface value, it is unmarshaled as an int64 if
+//     the JSON data does not contain a "." character and parses as an integer successfully and
+//     does not overflow int64. Otherwise, the number is unmarshaled as a float64.
+//   - If a syntax error is returned, it will not be of type encoding/json#SyntaxError,
+//     but will be recognizeable by this package's IsSyntaxError() function.
 func NewDecoderCaseSensitivePreserveInts(r io.Reader) Decoder {
 	d := internaljson.NewDecoder(r)
 	d.CaseSensitive()
@@ -51,13 +51,13 @@ func NewDecoderCaseSensitivePreserveInts(r io.Reader) Decoder {
 // UnmarshalCaseSensitivePreserveInts parses the JSON-encoded data and stores the result in the value pointed to by v.
 //
 // UnmarshalCaseSensitivePreserveInts matches the behavior of encoding/json#Unmarshal, with the following changes:
-// - When unmarshaling into a struct, JSON keys must case-sensitively match `json` tag names (for tagged struct fields)
-//   or struct field names (for untagged struct fields), or they are treated as unknown fields and discarded.
-// - When unmarshaling a number into an interface value, it is unmarshaled as an int64 if
-//   the JSON data does not contain a "." character and parses as an integer successfully and
-//   does not overflow int64. Otherwise, the number is unmarshaled as a float64.
-// - If a syntax error is returned, it will not be of type encoding/json#SyntaxError,
-//   but will be recognizeable by this package's IsSyntaxError() function.
+//   - When unmarshaling into a struct, JSON keys must case-sensitively match `json` tag names (for tagged struct fields)
+//     or struct field names (for untagged struct fields), or they are treated as unknown fields and discarded.
+//   - When unmarshaling a number into an interface value, it is unmarshaled as an int64 if
+//     the JSON data does not contain a "." character and parses as an integer successfully and
+//     does not overflow int64. Otherwise, the number is unmarshaled as a float64.
+//   - If a syntax error is returned, it will not be of type encoding/json#SyntaxError,
+//     but will be recognizeable by this package's IsSyntaxError() function.
 func UnmarshalCaseSensitivePreserveInts(data []byte, v interface{}) error {
 	return internaljson.Unmarshal(
 		data,
@@ -84,6 +84,8 @@ const (
 // and a list of the strict failures (if any) are returned. If no `strictOptions` are selected,
 // all supported strict checks are performed.
 //
+// Strict errors returned will implement the FieldError interface for the specific erroneous fields.
+//
 // Currently supported strict checks are:
 // - DisallowDuplicateFields: ensure the data contains no duplicate fields
 // - DisallowUnknownFields: ensure the data contains no unknown fields (when decoding into typed structs)
@@ -137,3 +139,12 @@ func SyntaxErrorOffset(err error) (isSyntaxError bool, offset int64) {
 		return false, 0
 	}
 }
+
+// FieldError is an error that provides access to the path of the erroneous field
+type FieldError interface {
+	error
+	// FieldPath provides the full path of the erroneous field within the json object.
+	FieldPath() string
+	// SetFieldPath updates the path of the erroneous field output in the error message.
+	SetFieldPath(path string)
+}
diff --git a/json_test.go b/json_test.go
index d0f7862..7f02978 100644
--- a/json_test.go
+++ b/json_test.go
@@ -139,7 +139,11 @@ func TestUnmarshal(t *testing.T) {
 				t.Fatalf("expected %d strict errors, got %v", len(tc.expectStrictErrs), strictErrors)
 			}
 			for i := range tc.expectStrictErrs {
-				if !strings.Contains(strictErrors[i].Error(), tc.expectStrictErrs[i]) {
+				strictFieldErr, ok := strictErrors[i].(FieldError)
+				if !ok {
+					t.Fatalf("strict error does not implement FieldError: %v", strictErrors[i])
+				}
+				if !strings.Contains(strictFieldErr.Error(), tc.expectStrictErrs[i]) {
 					t.Fatalf("expected strict errors:\n  %s\ngot:\n  %v", strings.Join(tc.expectStrictErrs, "\n  "), strictErrors)
 				}
 			}

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/share/gocode/src/sigs.k8s.io/json/internal/golang/encoding/json/fuzz_test.go

No differences were encountered in the control files

More details

Full run details