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.go51
1 files changed, 30 insertions, 21 deletions
diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go
index 705bc2e17a7..530e8521dc5 100644
--- a/libgo/go/encoding/json/decode.go
+++ b/libgo/go/encoding/json/decode.go
@@ -48,6 +48,13 @@ import (
// map[string]interface{}, for JSON objects
// nil for JSON null
//
+// To unmarshal a JSON array into a slice, Unmarshal resets the slice to nil
+// and then appends each element to the slice.
+//
+// To unmarshal a JSON object into a map, Unmarshal replaces the map
+// with an empty map and then adds key-value pairs from the object to
+// the map.
+//
// If a JSON value is not appropriate for a given target type,
// or if a JSON number overflows the target type, Unmarshal
// skips that field and completes the unmarshalling as best it can.
@@ -90,8 +97,9 @@ type Unmarshaler interface {
// An UnmarshalTypeError describes a JSON value that was
// not appropriate for a value of a specific Go type.
type UnmarshalTypeError struct {
- Value string // description of JSON value - "bool", "array", "number -5"
- Type reflect.Type // type of Go value it could not be assigned to
+ Value string // description of JSON value - "bool", "array", "number -5"
+ Type reflect.Type // type of Go value it could not be assigned to
+ Offset int64 // error occurred after reading Offset bytes
}
func (e *UnmarshalTypeError) Error() string {
@@ -377,7 +385,7 @@ func (d *decodeState) array(v reflect.Value) {
return
}
if ut != nil {
- d.saveError(&UnmarshalTypeError{"array", v.Type()})
+ d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
d.off--
d.next()
return
@@ -396,7 +404,7 @@ func (d *decodeState) array(v reflect.Value) {
// Otherwise it's invalid.
fallthrough
default:
- d.saveError(&UnmarshalTypeError{"array", v.Type()})
+ d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
d.off--
d.next()
return
@@ -485,7 +493,7 @@ func (d *decodeState) object(v reflect.Value) {
return
}
if ut != nil {
- d.saveError(&UnmarshalTypeError{"object", v.Type()})
+ d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
d.off--
d.next() // skip over { } in input
return
@@ -504,7 +512,7 @@ func (d *decodeState) object(v reflect.Value) {
// map must have string kind
t := v.Type()
if t.Key().Kind() != reflect.String {
- d.saveError(&UnmarshalTypeError{"object", v.Type()})
+ d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
d.off--
d.next() // skip over { } in input
return
@@ -515,7 +523,7 @@ func (d *decodeState) object(v reflect.Value) {
case reflect.Struct:
default:
- d.saveError(&UnmarshalTypeError{"object", v.Type()})
+ d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
d.off--
d.next() // skip over { } in input
return
@@ -599,7 +607,7 @@ func (d *decodeState) object(v reflect.Value) {
case string:
d.literalStore([]byte(qv), subv, true)
default:
- d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", item, v.Type()))
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type()))
}
} else {
d.value(subv)
@@ -646,7 +654,7 @@ func (d *decodeState) convertNumber(s string) (interface{}, error) {
}
f, err := strconv.ParseFloat(s, 64)
if err != nil {
- return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0)}
+ return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)}
}
return f, nil
}
@@ -679,8 +687,9 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
- d.saveError(&UnmarshalTypeError{"string", v.Type()})
+ d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
}
+ return
}
s, ok := unquoteBytes(item)
if !ok {
@@ -713,7 +722,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
- d.saveError(&UnmarshalTypeError{"bool", v.Type()})
+ d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
}
case reflect.Bool:
v.SetBool(value)
@@ -721,7 +730,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if v.NumMethod() == 0 {
v.Set(reflect.ValueOf(value))
} else {
- d.saveError(&UnmarshalTypeError{"bool", v.Type()})
+ d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
}
}
@@ -736,10 +745,10 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
}
switch v.Kind() {
default:
- d.saveError(&UnmarshalTypeError{"string", v.Type()})
+ d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
case reflect.Slice:
- if v.Type() != byteSliceType {
- d.saveError(&UnmarshalTypeError{"string", v.Type()})
+ if v.Type().Elem().Kind() != reflect.Uint8 {
+ d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
break
}
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
@@ -755,7 +764,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if v.NumMethod() == 0 {
v.Set(reflect.ValueOf(string(s)))
} else {
- d.saveError(&UnmarshalTypeError{"string", v.Type()})
+ d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
}
}
@@ -777,7 +786,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
- d.error(&UnmarshalTypeError{"number", v.Type()})
+ d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
}
case reflect.Interface:
n, err := d.convertNumber(s)
@@ -786,7 +795,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
break
}
if v.NumMethod() != 0 {
- d.saveError(&UnmarshalTypeError{"number", v.Type()})
+ d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
break
}
v.Set(reflect.ValueOf(n))
@@ -794,7 +803,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.ParseInt(s, 10, 64)
if err != nil || v.OverflowInt(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+ d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
break
}
v.SetInt(n)
@@ -802,7 +811,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n, err := strconv.ParseUint(s, 10, 64)
if err != nil || v.OverflowUint(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+ d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
break
}
v.SetUint(n)
@@ -810,7 +819,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
case reflect.Float32, reflect.Float64:
n, err := strconv.ParseFloat(s, v.Type().Bits())
if err != nil || v.OverflowFloat(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+ d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
break
}
v.SetFloat(n)