Skip to content

Commit

Permalink
json: check keyed before unmarshaler
Browse files Browse the repository at this point in the history
  • Loading branch information
niemeyer committed May 23, 2016
1 parent 833b186 commit 84d0daa
Showing 1 changed file with 17 additions and 19 deletions.
36 changes: 17 additions & 19 deletions internal/json/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,10 +440,10 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler,
}
if v.Type().NumMethod() > 0 {
if u, ok := v.Interface().(Unmarshaler); ok {
return u, nil, reflect.Value{}
return u, nil, v
}
if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
return nil, u, reflect.Value{}
return nil, u, v
}
}
v = v.Elem()
Expand Down Expand Up @@ -565,6 +565,9 @@ var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
func (d *decodeState) object(v reflect.Value) {
// Check for unmarshaler.
u, ut, pv := d.indirect(v, false)
if d.storeKeyed(pv) {
return
}
if u != nil {
d.off--
err := u.UnmarshalJSON(d.next())
Expand All @@ -581,10 +584,6 @@ func (d *decodeState) object(v reflect.Value) {
}
v = pv

if d.storeKeyed(v) {
return
}

// Decoding into nil interface? Switch to non-reflect code.
if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
v.Set(reflect.ValueOf(d.objectInterface()))
Expand Down Expand Up @@ -735,6 +734,9 @@ func (d *decodeState) object(v reflect.Value) {
func (d *decodeState) function(v reflect.Value) {
// Check for unmarshaler.
u, ut, pv := d.indirect(v, false)
if d.storeKeyed(pv) {
return
}
if u != nil {
d.off--
err := u.UnmarshalJSON(d.next())
Expand All @@ -751,10 +753,6 @@ func (d *decodeState) function(v reflect.Value) {
}
v = pv

if d.storeKeyed(v) {
return
}

// Decoding into nil interface? Switch to non-reflect code.
if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
v.Set(reflect.ValueOf(d.functionInterface()))
Expand Down Expand Up @@ -974,19 +972,16 @@ func (d *decodeState) keyed() (interface{}, bool) {
// Look-ahead first key to check for a keyed document extension.
d.nextscan.reset()
var start, end int
Loop:
for i, c := range d.data[d.off:] {
switch op := d.nextscan.step(&d.nextscan, c); op {
case scanSkipSpace:
case scanSkipSpace, scanContinue:
continue
case scanBeginLiteral, scanBeginName:
start = i
case scanContinue:
case scanEnd, scanParam:
end = i
break Loop
default:
d.error(errPhase)
continue
}
end = i
break
}

var key []byte
Expand Down Expand Up @@ -1026,12 +1021,15 @@ func (d *decodeState) storeKeyed(v reflect.Value) bool {
}

func (d *decodeState) storeValue(v reflect.Value, from interface{}) bool {
vt := v.Type()
fromv := reflect.ValueOf(from)
for fromv.Kind() == reflect.Ptr && !fromv.IsNil() {
fromv = fromv.Elem()
}
fromt := fromv.Type()
for v.Kind() == reflect.Ptr && !v.IsNil() {
v = v.Elem()
}
vt := v.Type()
if fromt.AssignableTo(vt) {
v.Set(fromv)
} else if fromt.ConvertibleTo(vt) {
Expand Down

0 comments on commit 84d0daa

Please sign in to comment.