summaryrefslogtreecommitdiff
path: root/libgo/go/encoding/json/decode.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/encoding/json/decode.go')
-rw-r--r--libgo/go/encoding/json/decode.go71
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: