diff options
Diffstat (limited to 'libgo/go/encoding/json/decode.go')
-rw-r--r-- | libgo/go/encoding/json/decode.go | 71 |
1 files changed, 49 insertions, 22 deletions
diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go index b46dac96f5d..6e6815ff131 100644 --- a/libgo/go/encoding/json/decode.go +++ b/libgo/go/encoding/json/decode.go @@ -52,6 +52,25 @@ import ( // an UnmarshalTypeError describing the earliest such error. // func Unmarshal(data []byte, v interface{}) error { + + // skip heavy processing for primitive values + var first byte + var i int + for i, first = range data { + if !isSpace(rune(first)) { + break + } + } + if first != '{' && first != '[' { + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Ptr || rv.IsNil() { + return &InvalidUnmarshalError{reflect.TypeOf(v)} + } + var d decodeState + d.literalStore(data[i:], rv.Elem(), false) + return d.savedError + } + d := new(decodeState).init(data) // Quick check for well-formedness. @@ -87,6 +106,7 @@ func (e *UnmarshalTypeError) Error() string { // An UnmarshalFieldError describes a JSON object key that // led to an unexported (and therefore unwritable) struct field. +// (No longer used; kept for compatibility.) type UnmarshalFieldError struct { Key string Type reflect.Type @@ -328,15 +348,19 @@ func (d *decodeState) array(v reflect.Value) { // Check type of target. switch v.Kind() { + case reflect.Interface: + if v.NumMethod() == 0 { + // Decoding into nil interface? Switch to non-reflect code. + v.Set(reflect.ValueOf(d.arrayInterface())) + return + } + // Otherwise it's invalid. + fallthrough default: d.saveError(&UnmarshalTypeError{"array", v.Type()}) d.off-- d.next() return - case reflect.Interface: - // Decoding into nil interface? Switch to non-reflect code. - v.Set(reflect.ValueOf(d.arrayInterface())) - return case reflect.Array: case reflect.Slice: break @@ -422,7 +446,7 @@ func (d *decodeState) object(v reflect.Value) { v = pv // Decoding into nil interface? Switch to non-reflect code. - if v.Kind() == reflect.Interface { + if v.Kind() == reflect.Interface && v.NumMethod() == 0 { v.Set(reflect.ValueOf(d.objectInterface())) return } @@ -430,9 +454,9 @@ func (d *decodeState) object(v reflect.Value) { // Check type of target: struct or map[string]T switch v.Kind() { case reflect.Map: - // map must have string type + // map must have string kind t := v.Type() - if t.Key() != reflect.TypeOf("") { + if t.Key().Kind() != reflect.String { d.saveError(&UnmarshalTypeError{"object", v.Type()}) break } @@ -440,11 +464,9 @@ func (d *decodeState) object(v reflect.Value) { v.Set(reflect.MakeMap(t)) } case reflect.Struct: + default: d.saveError(&UnmarshalTypeError{"object", v.Type()}) - } - - if !v.IsValid() { d.off-- d.next() // skip over { } in input return @@ -509,15 +531,6 @@ func (d *decodeState) object(v reflect.Value) { } subv = subv.Field(i) } - } else { - // To give a good error, a quick scan for unexported fields in top level. - st := v.Type() - for i := 0; i < st.NumField(); i++ { - f := st.Field(i) - if f.PkgPath != "" && strings.EqualFold(f.Name, key) { - d.saveError(&UnmarshalFieldError{key, st, f}) - } - } } } @@ -536,10 +549,12 @@ func (d *decodeState) object(v reflect.Value) { } else { d.value(subv) } + // Write value back to map; // if using struct, subv points into struct already. if v.Kind() == reflect.Map { - v.SetMapIndex(reflect.ValueOf(key), subv) + kv := reflect.ValueOf(key).Convert(v.Type().Key()) + v.SetMapIndex(kv, subv) } // Next token must be , or }. @@ -625,7 +640,11 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool case reflect.Bool: v.SetBool(value) case reflect.Interface: - v.Set(reflect.ValueOf(value)) + if v.NumMethod() == 0 { + v.Set(reflect.ValueOf(value)) + } else { + d.saveError(&UnmarshalTypeError{"bool", v.Type()}) + } } case '"': // string @@ -655,7 +674,11 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool case reflect.String: v.SetString(string(s)) case reflect.Interface: - v.Set(reflect.ValueOf(string(s))) + if v.NumMethod() == 0 { + v.Set(reflect.ValueOf(string(s))) + } else { + d.saveError(&UnmarshalTypeError{"string", v.Type()}) + } } default: // number @@ -684,6 +707,10 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool d.saveError(err) break } + if v.NumMethod() != 0 { + d.saveError(&UnmarshalTypeError{"number", v.Type()}) + break + } v.Set(reflect.ValueOf(n)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |