mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
encoding/json: use reflect.TypeAssert
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>
This commit is contained in:
parent
4c20f7f15a
commit
e6605a1bcc
6 changed files with 30 additions and 27 deletions
|
|
@ -482,11 +482,11 @@ func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnm
|
||||||
v.Set(reflect.New(v.Type().Elem()))
|
v.Set(reflect.New(v.Type().Elem()))
|
||||||
}
|
}
|
||||||
if v.Type().NumMethod() > 0 && v.CanInterface() {
|
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{}
|
return u, nil, reflect.Value{}
|
||||||
}
|
}
|
||||||
if !decodingNull {
|
if !decodingNull {
|
||||||
if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
|
if u, ok := reflect.TypeAssert[encoding.TextUnmarshaler](v); ok {
|
||||||
return nil, u, reflect.Value{}
|
return nil, u, reflect.Value{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -475,7 +475,7 @@ func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
|
||||||
e.WriteString("null")
|
e.WriteString("null")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m, ok := v.Interface().(Marshaler)
|
m, ok := reflect.TypeAssert[Marshaler](v)
|
||||||
if !ok {
|
if !ok {
|
||||||
e.WriteString("null")
|
e.WriteString("null")
|
||||||
return
|
return
|
||||||
|
|
@ -498,7 +498,7 @@ func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
|
||||||
e.WriteString("null")
|
e.WriteString("null")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m := va.Interface().(Marshaler)
|
m, _ := reflect.TypeAssert[Marshaler](va)
|
||||||
b, err := m.MarshalJSON()
|
b, err := m.MarshalJSON()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
e.Grow(len(b))
|
e.Grow(len(b))
|
||||||
|
|
@ -516,7 +516,7 @@ func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
|
||||||
e.WriteString("null")
|
e.WriteString("null")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m, ok := v.Interface().(encoding.TextMarshaler)
|
m, ok := reflect.TypeAssert[encoding.TextMarshaler](v)
|
||||||
if !ok {
|
if !ok {
|
||||||
e.WriteString("null")
|
e.WriteString("null")
|
||||||
return
|
return
|
||||||
|
|
@ -534,7 +534,7 @@ func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
|
||||||
e.WriteString("null")
|
e.WriteString("null")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m := va.Interface().(encoding.TextMarshaler)
|
m, _ := reflect.TypeAssert[encoding.TextMarshaler](va)
|
||||||
b, err := m.MarshalText()
|
b, err := m.MarshalText()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e.error(&MarshalerError{v.Type(), err, "MarshalText"})
|
e.error(&MarshalerError{v.Type(), err, "MarshalText"})
|
||||||
|
|
@ -991,7 +991,7 @@ func resolveKeyName(k reflect.Value) (string, error) {
|
||||||
if k.Kind() == reflect.String {
|
if k.Kind() == reflect.String {
|
||||||
return k.String(), nil
|
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() {
|
if k.Kind() == reflect.Pointer && k.IsNil() {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,8 @@ func MarshalFunc[T any](fn func(T) ([]byte, error)) *Marshalers {
|
||||||
typFnc := typedMarshaler{
|
typFnc := typedMarshaler{
|
||||||
typ: t,
|
typ: t,
|
||||||
fnc: func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
|
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 {
|
if err != nil {
|
||||||
err = wrapSkipFunc(err, "marshal function of type func(T) ([]byte, error)")
|
err = wrapSkipFunc(err, "marshal function of type func(T) ([]byte, error)")
|
||||||
if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
|
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)
|
xe := export.Encoder(enc)
|
||||||
prevDepth, prevLength := xe.Tokens.DepthLength()
|
prevDepth, prevLength := xe.Tokens.DepthLength()
|
||||||
xe.Flags.Set(jsonflags.WithinArshalCall | 1)
|
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)
|
xe.Flags.Set(jsonflags.WithinArshalCall | 0)
|
||||||
currDepth, currLength := xe.Tokens.DepthLength()
|
currDepth, currLength := xe.Tokens.DepthLength()
|
||||||
if err == nil && (prevDepth != currDepth || prevLength+1 != currLength) {
|
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 {
|
if err != nil {
|
||||||
return err // must be a syntactic or I/O error
|
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 {
|
if err != nil {
|
||||||
err = wrapSkipFunc(err, "unmarshal function of type func([]byte, T) error")
|
err = wrapSkipFunc(err, "unmarshal function of type func([]byte, T) error")
|
||||||
if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
|
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)
|
xd := export.Decoder(dec)
|
||||||
prevDepth, prevLength := xd.Tokens.DepthLength()
|
prevDepth, prevLength := xd.Tokens.DepthLength()
|
||||||
xd.Flags.Set(jsonflags.WithinArshalCall | 1)
|
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)
|
xd.Flags.Set(jsonflags.WithinArshalCall | 0)
|
||||||
currDepth, currLength := xd.Tokens.DepthLength()
|
currDepth, currLength := xd.Tokens.DepthLength()
|
||||||
if err == nil && (prevDepth != currDepth || prevLength+1 != currLength) {
|
if err == nil && (prevDepth != currDepth || prevLength+1 != currLength) {
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,7 @@ func marshalInlinedFallbackAll(enc *jsontext.Encoder, va addressableValue, mo *j
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.Type() == jsontextValueType {
|
if v.Type() == jsontextValueType {
|
||||||
// TODO(https://go.dev/issue/62121): Use reflect.Value.AssertTo.
|
b, _ := reflect.TypeAssert[jsontext.Value](v.Value)
|
||||||
b := *v.Addr().Interface().(*jsontext.Value)
|
|
||||||
if len(b) == 0 { // TODO: Should this be nil? What if it were all whitespace?
|
if len(b) == 0 { // TODO: Should this be nil? What if it were all whitespace?
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -174,7 +173,7 @@ func unmarshalInlinedFallbackNext(dec *jsontext.Decoder, va addressableValue, uo
|
||||||
v = v.indirect(true)
|
v = v.indirect(true)
|
||||||
|
|
||||||
if v.Type() == jsontextValueType {
|
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?
|
if len(*b) == 0 { // TODO: Should this be nil? What if it were all whitespace?
|
||||||
*b = append(*b, '{')
|
*b = append(*b, '{')
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
||||||
(needAddr && va.forcedAddr) {
|
(needAddr && va.forcedAddr) {
|
||||||
return prevMarshal(enc, va, mo)
|
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) {
|
if err := export.Encoder(enc).AppendRaw('"', false, func(b []byte) ([]byte, error) {
|
||||||
b2, err := marshaler.MarshalText()
|
b2, err := marshaler.MarshalText()
|
||||||
return append(b, b2...), err
|
return append(b, b2...), err
|
||||||
|
|
@ -137,7 +137,7 @@ func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
||||||
(needAddr && va.forcedAddr) {
|
(needAddr && va.forcedAddr) {
|
||||||
return prevMarshal(enc, va, mo)
|
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 {
|
if err := export.Encoder(enc).AppendRaw('"', false, appender.AppendText); err != nil {
|
||||||
err = wrapSkipFunc(err, "append method")
|
err = wrapSkipFunc(err, "append method")
|
||||||
if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
|
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()) {
|
((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
|
||||||
return prevMarshal(enc, va, mo)
|
return prevMarshal(enc, va, mo)
|
||||||
}
|
}
|
||||||
marshaler := va.Addr().Interface().(Marshaler)
|
marshaler, _ := reflect.TypeAssert[Marshaler](va.Addr())
|
||||||
val, err := marshaler.MarshalJSON()
|
val, err := marshaler.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = wrapSkipFunc(err, "marshal method")
|
err = wrapSkipFunc(err, "marshal method")
|
||||||
|
|
@ -194,7 +194,8 @@ func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
||||||
xe := export.Encoder(enc)
|
xe := export.Encoder(enc)
|
||||||
prevDepth, prevLength := xe.Tokens.DepthLength()
|
prevDepth, prevLength := xe.Tokens.DepthLength()
|
||||||
xe.Flags.Set(jsonflags.WithinArshalCall | 1)
|
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)
|
xe.Flags.Set(jsonflags.WithinArshalCall | 0)
|
||||||
currDepth, currLength := xe.Tokens.DepthLength()
|
currDepth, currLength := xe.Tokens.DepthLength()
|
||||||
if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
|
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)
|
return newUnmarshalErrorAfter(dec, t, errNonStringValue)
|
||||||
}
|
}
|
||||||
s := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
|
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 {
|
if err := unmarshaler.UnmarshalText(s); err != nil {
|
||||||
err = wrapSkipFunc(err, "unmarshal method")
|
err = wrapSkipFunc(err, "unmarshal method")
|
||||||
if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
|
if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
|
||||||
|
|
@ -260,7 +261,7 @@ func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err // must be a syntactic or I/O error
|
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 {
|
if err := unmarshaler.UnmarshalJSON(val); err != nil {
|
||||||
err = wrapSkipFunc(err, "unmarshal method")
|
err = wrapSkipFunc(err, "unmarshal method")
|
||||||
if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
|
if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
|
||||||
|
|
@ -284,7 +285,8 @@ func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
||||||
xd := export.Decoder(dec)
|
xd := export.Decoder(dec)
|
||||||
prevDepth, prevLength := xd.Tokens.DepthLength()
|
prevDepth, prevLength := xd.Tokens.DepthLength()
|
||||||
xd.Flags.Set(jsonflags.WithinArshalCall | 1)
|
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)
|
xd.Flags.Set(jsonflags.WithinArshalCall | 0)
|
||||||
currDepth, currLength := xd.Tokens.DepthLength()
|
currDepth, currLength := xd.Tokens.DepthLength()
|
||||||
if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
|
if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
|
||||||
|
|
|
||||||
|
|
@ -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"))
|
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, _ = reflect.TypeAssert[time.Duration](va.Value)
|
||||||
m.td = *va.Addr().Interface().(*time.Duration)
|
|
||||||
k := stringOrNumberKind(!m.isNumeric() || xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers))
|
k := stringOrNumberKind(!m.isNumeric() || xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers))
|
||||||
if err := xe.AppendRaw(k, true, m.appendMarshal); err != nil {
|
if err := xe.AppendRaw(k, true, m.appendMarshal); err != nil {
|
||||||
if !isSyntacticError(err) && !export.IsIOError(err) {
|
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)
|
stringify := !u.isNumeric() || xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers)
|
||||||
var flags jsonwire.ValueFlags
|
var flags jsonwire.ValueFlags
|
||||||
td := va.Addr().Interface().(*time.Duration)
|
td, _ := reflect.TypeAssert[*time.Duration](va.Addr())
|
||||||
val, err := xd.ReadValue(&flags)
|
val, err := xd.ReadValue(&flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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, _ = reflect.TypeAssert[time.Time](va.Value)
|
||||||
m.tt = *va.Addr().Interface().(*time.Time)
|
|
||||||
k := stringOrNumberKind(!m.isNumeric() || xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers))
|
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 err := xe.AppendRaw(k, !m.hasCustomFormat(), m.appendMarshal); err != nil {
|
||||||
if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
|
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)
|
stringify := !u.isNumeric() || xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers)
|
||||||
var flags jsonwire.ValueFlags
|
var flags jsonwire.ValueFlags
|
||||||
tt := va.Addr().Interface().(*time.Time)
|
tt, _ := reflect.TypeAssert[*time.Time](va.Addr())
|
||||||
val, err := xd.ReadValue(&flags)
|
val, err := xd.ReadValue(&flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue