]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/json: use reflect.TypeAssert
authorJoe Tsai <joetsai@digital-static.net>
Sun, 22 Jun 2025 04:01:32 +0000 (21:01 -0700)
committerJoseph Tsai <joetsai@digital-static.net>
Wed, 10 Sep 2025 00:22:28 +0000 (17:22 -0700)
Updates #62121

Change-Id: Ic3c4fe84a5dacfd8270aba0d5dd59f83f0a9030f
Reviewed-on: https://go-review.googlesource.com/c/go/+/701955
Reviewed-by: Mark Freeman <markfreeman@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/encoding/json/decode.go
src/encoding/json/encode.go
src/encoding/json/v2/arshal_funcs.go
src/encoding/json/v2/arshal_inlined.go
src/encoding/json/v2/arshal_methods.go
src/encoding/json/v2/arshal_time.go

index fc29296c0f464f4eb1927b3fa9a7d49b808eb445..46f9ed2da9bc7535e09bafb1c204e8c941cec084 100644 (file)
@@ -482,11 +482,11 @@ func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnm
                        v.Set(reflect.New(v.Type().Elem()))
                }
                if v.Type().NumMethod() > 0 && v.CanInterface() {
-                       if u, ok := v.Interface().(Unmarshaler); ok {
+                       if u, ok := reflect.TypeAssert[Unmarshaler](v); ok {
                                return u, nil, reflect.Value{}
                        }
                        if !decodingNull {
-                               if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
+                               if u, ok := reflect.TypeAssert[encoding.TextUnmarshaler](v); ok {
                                        return nil, u, reflect.Value{}
                                }
                        }
index 29fcc91fd7b0dabaa6d688a2623e5cedf2a37a66..1b7942dd3ad3f4e70e728a2a0a0f4b876d385a07 100644 (file)
@@ -475,7 +475,7 @@ func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
                e.WriteString("null")
                return
        }
-       m, ok := v.Interface().(Marshaler)
+       m, ok := reflect.TypeAssert[Marshaler](v)
        if !ok {
                e.WriteString("null")
                return
@@ -498,7 +498,7 @@ func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
                e.WriteString("null")
                return
        }
-       m := va.Interface().(Marshaler)
+       m, _ := reflect.TypeAssert[Marshaler](va)
        b, err := m.MarshalJSON()
        if err == nil {
                e.Grow(len(b))
@@ -516,7 +516,7 @@ func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
                e.WriteString("null")
                return
        }
-       m, ok := v.Interface().(encoding.TextMarshaler)
+       m, ok := reflect.TypeAssert[encoding.TextMarshaler](v)
        if !ok {
                e.WriteString("null")
                return
@@ -534,7 +534,7 @@ func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
                e.WriteString("null")
                return
        }
-       m := va.Interface().(encoding.TextMarshaler)
+       m, _ := reflect.TypeAssert[encoding.TextMarshaler](va)
        b, err := m.MarshalText()
        if err != nil {
                e.error(&MarshalerError{v.Type(), err, "MarshalText"})
@@ -991,7 +991,7 @@ func resolveKeyName(k reflect.Value) (string, error) {
        if k.Kind() == reflect.String {
                return k.String(), nil
        }
-       if tm, ok := k.Interface().(encoding.TextMarshaler); ok {
+       if tm, ok := reflect.TypeAssert[encoding.TextMarshaler](k); ok {
                if k.Kind() == reflect.Pointer && k.IsNil() {
                        return "", nil
                }
index 5986c5473268d28681cb246e37535603536d6b8c..673caf3c37693d8d571d809481300fbe571960dd 100644 (file)
@@ -177,7 +177,8 @@ func MarshalFunc[T any](fn func(T) ([]byte, error)) *Marshalers {
        typFnc := typedMarshaler{
                typ: t,
                fnc: func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
-                       val, err := fn(va.castTo(t).Interface().(T))
+                       v, _ := reflect.TypeAssert[T](va.castTo(t))
+                       val, err := fn(v)
                        if err != nil {
                                err = wrapSkipFunc(err, "marshal function of type func(T) ([]byte, error)")
                                if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
@@ -222,7 +223,8 @@ func MarshalToFunc[T any](fn func(*jsontext.Encoder, T) error) *Marshalers {
                        xe := export.Encoder(enc)
                        prevDepth, prevLength := xe.Tokens.DepthLength()
                        xe.Flags.Set(jsonflags.WithinArshalCall | 1)
-                       err := fn(enc, va.castTo(t).Interface().(T))
+                       v, _ := reflect.TypeAssert[T](va.castTo(t))
+                       err := fn(enc, v)
                        xe.Flags.Set(jsonflags.WithinArshalCall | 0)
                        currDepth, currLength := xe.Tokens.DepthLength()
                        if err == nil && (prevDepth != currDepth || prevLength+1 != currLength) {
@@ -269,7 +271,8 @@ func UnmarshalFunc[T any](fn func([]byte, T) error) *Unmarshalers {
                        if err != nil {
                                return err // must be a syntactic or I/O error
                        }
-                       err = fn(val, va.castTo(t).Interface().(T))
+                       v, _ := reflect.TypeAssert[T](va.castTo(t))
+                       err = fn(val, v)
                        if err != nil {
                                err = wrapSkipFunc(err, "unmarshal function of type func([]byte, T) error")
                                if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
@@ -304,7 +307,8 @@ func UnmarshalFromFunc[T any](fn func(*jsontext.Decoder, T) error) *Unmarshalers
                        xd := export.Decoder(dec)
                        prevDepth, prevLength := xd.Tokens.DepthLength()
                        xd.Flags.Set(jsonflags.WithinArshalCall | 1)
-                       err := fn(dec, va.castTo(t).Interface().(T))
+                       v, _ := reflect.TypeAssert[T](va.castTo(t))
+                       err := fn(dec, v)
                        xd.Flags.Set(jsonflags.WithinArshalCall | 0)
                        currDepth, currLength := xd.Tokens.DepthLength()
                        if err == nil && (prevDepth != currDepth || prevLength+1 != currLength) {
index a25314450251f4b37085ff29b321c6f688886282..d911bfa1c04d4554a7f11ab56ca6f4c936c9a85d 100644 (file)
@@ -50,8 +50,7 @@ func marshalInlinedFallbackAll(enc *jsontext.Encoder, va addressableValue, mo *j
        }
 
        if v.Type() == jsontextValueType {
-               // TODO(https://go.dev/issue/62121): Use reflect.Value.AssertTo.
-               b := *v.Addr().Interface().(*jsontext.Value)
+               b, _ := reflect.TypeAssert[jsontext.Value](v.Value)
                if len(b) == 0 { // TODO: Should this be nil? What if it were all whitespace?
                        return nil
                }
@@ -174,7 +173,7 @@ func unmarshalInlinedFallbackNext(dec *jsontext.Decoder, va addressableValue, uo
        v = v.indirect(true)
 
        if v.Type() == jsontextValueType {
-               b := v.Addr().Interface().(*jsontext.Value)
+               b, _ := reflect.TypeAssert[*jsontext.Value](v.Addr())
                if len(*b) == 0 { // TODO: Should this be nil? What if it were all whitespace?
                        *b = append(*b, '{')
                } else {
index 099be298c269d16cccfbf364d64a8bda06018a38..664c3927cc3225f79a37fe87083c73ed1a9577fb 100644 (file)
@@ -111,7 +111,7 @@ func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
                                (needAddr && va.forcedAddr) {
                                return prevMarshal(enc, va, mo)
                        }
-                       marshaler := va.Addr().Interface().(encoding.TextMarshaler)
+                       marshaler, _ := reflect.TypeAssert[encoding.TextMarshaler](va.Addr())
                        if err := export.Encoder(enc).AppendRaw('"', false, func(b []byte) ([]byte, error) {
                                b2, err := marshaler.MarshalText()
                                return append(b, b2...), err
@@ -137,7 +137,7 @@ func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
                                (needAddr && va.forcedAddr) {
                                return prevMarshal(enc, va, mo)
                        }
-                       appender := va.Addr().Interface().(encoding.TextAppender)
+                       appender, _ := reflect.TypeAssert[encoding.TextAppender](va.Addr())
                        if err := export.Encoder(enc).AppendRaw('"', false, appender.AppendText); err != nil {
                                err = wrapSkipFunc(err, "append method")
                                if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
@@ -160,7 +160,7 @@ func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
                                ((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
                                return prevMarshal(enc, va, mo)
                        }
-                       marshaler := va.Addr().Interface().(Marshaler)
+                       marshaler, _ := reflect.TypeAssert[Marshaler](va.Addr())
                        val, err := marshaler.MarshalJSON()
                        if err != nil {
                                err = wrapSkipFunc(err, "marshal method")
@@ -194,7 +194,8 @@ func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
                        xe := export.Encoder(enc)
                        prevDepth, prevLength := xe.Tokens.DepthLength()
                        xe.Flags.Set(jsonflags.WithinArshalCall | 1)
-                       err := va.Addr().Interface().(MarshalerTo).MarshalJSONTo(enc)
+                       marshaler, _ := reflect.TypeAssert[MarshalerTo](va.Addr())
+                       err := marshaler.MarshalJSONTo(enc)
                        xe.Flags.Set(jsonflags.WithinArshalCall | 0)
                        currDepth, currLength := xe.Tokens.DepthLength()
                        if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
@@ -233,7 +234,7 @@ func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
                                return newUnmarshalErrorAfter(dec, t, errNonStringValue)
                        }
                        s := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
-                       unmarshaler := va.Addr().Interface().(encoding.TextUnmarshaler)
+                       unmarshaler, _ := reflect.TypeAssert[encoding.TextUnmarshaler](va.Addr())
                        if err := unmarshaler.UnmarshalText(s); err != nil {
                                err = wrapSkipFunc(err, "unmarshal method")
                                if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
@@ -260,7 +261,7 @@ func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
                        if err != nil {
                                return err // must be a syntactic or I/O error
                        }
-                       unmarshaler := va.Addr().Interface().(Unmarshaler)
+                       unmarshaler, _ := reflect.TypeAssert[Unmarshaler](va.Addr())
                        if err := unmarshaler.UnmarshalJSON(val); err != nil {
                                err = wrapSkipFunc(err, "unmarshal method")
                                if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
@@ -284,7 +285,8 @@ func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
                        xd := export.Decoder(dec)
                        prevDepth, prevLength := xd.Tokens.DepthLength()
                        xd.Flags.Set(jsonflags.WithinArshalCall | 1)
-                       err := va.Addr().Interface().(UnmarshalerFrom).UnmarshalJSONFrom(dec)
+                       unmarshaler, _ := reflect.TypeAssert[UnmarshalerFrom](va.Addr())
+                       err := unmarshaler.UnmarshalJSONFrom(dec)
                        xd.Flags.Set(jsonflags.WithinArshalCall | 0)
                        currDepth, currLength := xd.Tokens.DepthLength()
                        if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
index ac29abe5021ca9352e32c972ff4da7579d64f9bc..70dca8a2943b45abd1a20b1bf6e1b643cf3a1112 100644 (file)
@@ -57,8 +57,7 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
                                return newMarshalErrorBefore(enc, t, errors.New("no default representation (see https://go.dev/issue/71631); specify an explicit format"))
                        }
 
-                       // TODO(https://go.dev/issue/62121): Use reflect.Value.AssertTo.
-                       m.td = *va.Addr().Interface().(*time.Duration)
+                       m.td, _ = reflect.TypeAssert[time.Duration](va.Value)
                        k := stringOrNumberKind(!m.isNumeric() || xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers))
                        if err := xe.AppendRaw(k, true, m.appendMarshal); err != nil {
                                if !isSyntacticError(err) && !export.IsIOError(err) {
@@ -85,7 +84,7 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
 
                        stringify := !u.isNumeric() || xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers)
                        var flags jsonwire.ValueFlags
-                       td := va.Addr().Interface().(*time.Duration)
+                       td, _ := reflect.TypeAssert[*time.Duration](va.Addr())
                        val, err := xd.ReadValue(&flags)
                        if err != nil {
                                return err
@@ -129,8 +128,7 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
                                }
                        }
 
-                       // TODO(https://go.dev/issue/62121): Use reflect.Value.AssertTo.
-                       m.tt = *va.Addr().Interface().(*time.Time)
+                       m.tt, _ = reflect.TypeAssert[time.Time](va.Value)
                        k := stringOrNumberKind(!m.isNumeric() || xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers))
                        if err := xe.AppendRaw(k, !m.hasCustomFormat(), m.appendMarshal); err != nil {
                                if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
@@ -156,7 +154,7 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
 
                        stringify := !u.isNumeric() || xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers)
                        var flags jsonwire.ValueFlags
-                       tt := va.Addr().Interface().(*time.Time)
+                       tt, _ := reflect.TypeAssert[*time.Time](va.Addr())
                        val, err := xd.ReadValue(&flags)
                        if err != nil {
                                return err