mirror of
https://github.com/golang/go
synced 2024-10-03 15:21:22 -06:00
encoding/json: simplify (*decodeState).indirect
Removes an incorrect code comment and some superfluous variables. The comment I removed says that struct fields which implement Unmarshaler must be pointers, even if they're in an addressable struct. That's not the case, and there's already a test in decode_test.go that demonstrates as much. Encoding/json has quite a few assignments of reflect.Values to extra variables – things like "iv := v" when there's no need to make a copy. I think these are left over from a previous version of the reflect API. If they aren't wanted, I wouldn't mind going through the package and getting rid of the rest of them. R=rsc CC=golang-dev https://golang.org/cl/6318047
This commit is contained in:
parent
32a0cbb881
commit
51ff2ef409
@ -265,47 +265,32 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler,
|
|||||||
v = v.Addr()
|
v = v.Addr()
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
var isUnmarshaler bool
|
|
||||||
if v.Type().NumMethod() > 0 {
|
|
||||||
// Remember that this is an unmarshaler,
|
|
||||||
// but wait to return it until after allocating
|
|
||||||
// the pointer (if necessary).
|
|
||||||
_, isUnmarshaler = v.Interface().(Unmarshaler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load value from interface, but only if the result will be
|
// Load value from interface, but only if the result will be
|
||||||
// usefully addressable.
|
// usefully addressable.
|
||||||
if iv := v; iv.Kind() == reflect.Interface && !iv.IsNil() {
|
if v.Kind() == reflect.Interface && !v.IsNil() {
|
||||||
e := iv.Elem()
|
e := v.Elem()
|
||||||
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
|
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
|
||||||
v = e
|
v = e
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pv := v
|
if v.Kind() != reflect.Ptr {
|
||||||
if pv.Kind() != reflect.Ptr {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if pv.Elem().Kind() != reflect.Ptr && decodingNull && pv.CanSet() {
|
if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
|
||||||
return nil, pv
|
break
|
||||||
}
|
}
|
||||||
if pv.IsNil() {
|
if v.IsNil() {
|
||||||
pv.Set(reflect.New(pv.Type().Elem()))
|
v.Set(reflect.New(v.Type().Elem()))
|
||||||
}
|
}
|
||||||
if isUnmarshaler {
|
if v.Type().NumMethod() > 0 {
|
||||||
// Using v.Interface().(Unmarshaler)
|
if unmarshaler, ok := v.Interface().(Unmarshaler); ok {
|
||||||
// here means that we have to use a pointer
|
return unmarshaler, reflect.Value{}
|
||||||
// as the struct field. We cannot use a value inside
|
}
|
||||||
// a pointer to a struct, because in that case
|
|
||||||
// v.Interface() is the value (x.f) not the pointer (&x.f).
|
|
||||||
// This is an unfortunate consequence of reflect.
|
|
||||||
// An alternative would be to look up the
|
|
||||||
// UnmarshalJSON method and return a FuncValue.
|
|
||||||
return v.Interface().(Unmarshaler), reflect.Value{}
|
|
||||||
}
|
}
|
||||||
v = pv.Elem()
|
v = v.Elem()
|
||||||
}
|
}
|
||||||
return nil, v
|
return nil, v
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user