json: preserve field name case by default

This matches the old JSON package behavior.
All lowercase names are not as standard as I believed,
and it seems less surprising to need to write

	type T struct { Field string "field" }

to get lower case (behavior after this CL) than it does to need
to write

	type T struct { Field string "Field" }

to preserve the case (behavior before this CL).

Also test and  fix unmarshal into non-nil interface
value or pointer.

Fixes #744.

R=r
CC=golang-dev
https://golang.org/cl/1013041
This commit is contained in:
Russ Cox 2010-04-27 10:24:00 -07:00
parent cc62bed075
commit bec40ba516
3 changed files with 164 additions and 127 deletions

View file

@ -20,7 +20,7 @@ import (
)
// Unmarshal parses the JSON-encoded data and stores the result
// in the value pointed at by v.
// in the value pointed to by v.
//
// Unmarshal traverses the value v recursively.
// If an encountered value implements the Unmarshaler interface,
@ -247,6 +247,10 @@ func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, refl
_, isUnmarshaler = v.Interface().(Unmarshaler)
}
if iv, ok := v.(*reflect.InterfaceValue); ok && !iv.IsNil() {
v = iv.Elem()
continue
}
pv, ok := v.(*reflect.PtrValue)
if !ok {
break
@ -255,7 +259,9 @@ func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, refl
if !isptrptr && wantptr && !isUnmarshaler {
return nil, pv
}
pv.PointTo(reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem()))
if pv.IsNil() {
pv.PointTo(reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem()))
}
if isUnmarshaler {
// Using v.Interface().(Unmarshaler)
// here means that we have to use a pointer
@ -436,11 +442,12 @@ func (d *decodeState) object(v reflect.Value) {
d.error(errPhase)
}
// Figure out
// Figure out field corresponding to key.
var subv reflect.Value
if mv != nil {
subv = reflect.MakeZero(mv.Type().(*reflect.MapType).Elem())
} else {
// First try for field with that tag.
for i := 0; i < sv.NumField(); i++ {
f := sv.Type().(*reflect.StructType).Field(i)
if f.Tag == key {
@ -449,7 +456,12 @@ func (d *decodeState) object(v reflect.Value) {
}
}
if subv == nil {
subv = sv.FieldByNameFunc(func(s string) bool { return matchName(key, s) })
// Second, exact match.
subv = sv.FieldByName(key)
if subv == nil {
// Third, case-insensitive match.
subv = sv.FieldByNameFunc(func(s string) bool { return matchName(key, s) })
}
}
}