Commit 51ff2ef4 authored by Micah Stetson's avatar Micah Stetson Committed by Russ Cox

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
parent 32a0cbb8
...@@ -265,47 +265,32 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, ...@@ -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
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment