|
@@ -48,6 +48,13 @@ import (
|
|
// map[string]interface{}, for JSON objects
|
|
// map[string]interface{}, for JSON objects
|
|
// nil for JSON null
|
|
// 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,
|
|
// If a JSON value is not appropriate for a given target type,
|
|
// or if a JSON number overflows the target type, Unmarshal
|
|
// or if a JSON number overflows the target type, Unmarshal
|
|
// skips that field and completes the unmarshalling as best it can.
|
|
// 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
|
|
// An UnmarshalTypeError describes a JSON value that was
|
|
// not appropriate for a value of a specific Go type.
|
|
// not appropriate for a value of a specific Go type.
|
|
type UnmarshalTypeError struct {
|
|
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 {
|
|
func (e *UnmarshalTypeError) Error() string {
|
|
@@ -378,7 +386,7 @@ func (d *decodeState) array(v reflect.Value) {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
if ut != nil {
|
|
if ut != nil {
|
|
- d.saveError(&UnmarshalTypeError{"array", v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
|
|
d.off--
|
|
d.off--
|
|
d.next()
|
|
d.next()
|
|
return
|
|
return
|
|
@@ -397,7 +405,7 @@ func (d *decodeState) array(v reflect.Value) {
|
|
// Otherwise it's invalid.
|
|
// Otherwise it's invalid.
|
|
fallthrough
|
|
fallthrough
|
|
default:
|
|
default:
|
|
- d.saveError(&UnmarshalTypeError{"array", v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
|
|
d.off--
|
|
d.off--
|
|
d.next()
|
|
d.next()
|
|
return
|
|
return
|
|
@@ -486,7 +494,7 @@ func (d *decodeState) object(v reflect.Value) {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
if ut != nil {
|
|
if ut != nil {
|
|
- d.saveError(&UnmarshalTypeError{"object", v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
|
|
d.off--
|
|
d.off--
|
|
d.next() // skip over { } in input
|
|
d.next() // skip over { } in input
|
|
return
|
|
return
|
|
@@ -505,7 +513,7 @@ func (d *decodeState) object(v reflect.Value) {
|
|
// map must have string kind
|
|
// map must have string kind
|
|
t := v.Type()
|
|
t := v.Type()
|
|
if t.Key().Kind() != reflect.String {
|
|
if t.Key().Kind() != reflect.String {
|
|
- d.saveError(&UnmarshalTypeError{"object", v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
|
|
d.off--
|
|
d.off--
|
|
d.next() // skip over { } in input
|
|
d.next() // skip over { } in input
|
|
return
|
|
return
|
|
@@ -516,7 +524,7 @@ func (d *decodeState) object(v reflect.Value) {
|
|
case reflect.Struct:
|
|
case reflect.Struct:
|
|
|
|
|
|
default:
|
|
default:
|
|
- d.saveError(&UnmarshalTypeError{"object", v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
|
|
d.off--
|
|
d.off--
|
|
d.next() // skip over { } in input
|
|
d.next() // skip over { } in input
|
|
return
|
|
return
|
|
@@ -600,7 +608,7 @@ func (d *decodeState) object(v reflect.Value) {
|
|
case string:
|
|
case string:
|
|
d.literalStore([]byte(qv), subv, true)
|
|
d.literalStore([]byte(qv), subv, true)
|
|
default:
|
|
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 {
|
|
} else {
|
|
d.value(subv)
|
|
d.value(subv)
|
|
@@ -647,7 +655,7 @@ func (d *decodeState) convertNumber(s string) (interface{}, error) {
|
|
}
|
|
}
|
|
f, err := strconv.ParseFloat(s, 64)
|
|
f, err := strconv.ParseFloat(s, 64)
|
|
if err != nil {
|
|
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
|
|
return f, nil
|
|
}
|
|
}
|
|
@@ -680,8 +688,9 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
|
if fromQuoted {
|
|
if fromQuoted {
|
|
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
|
|
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
|
|
} else {
|
|
} else {
|
|
- d.saveError(&UnmarshalTypeError{"string", v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
|
|
}
|
|
}
|
|
|
|
+ return
|
|
}
|
|
}
|
|
s, ok := unquoteBytes(item)
|
|
s, ok := unquoteBytes(item)
|
|
if !ok {
|
|
if !ok {
|
|
@@ -714,7 +723,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
|
if fromQuoted {
|
|
if fromQuoted {
|
|
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
|
|
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
|
|
} else {
|
|
} else {
|
|
- d.saveError(&UnmarshalTypeError{"bool", v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
|
|
}
|
|
}
|
|
case reflect.Bool:
|
|
case reflect.Bool:
|
|
v.SetBool(value)
|
|
v.SetBool(value)
|
|
@@ -722,7 +731,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
|
if v.NumMethod() == 0 {
|
|
if v.NumMethod() == 0 {
|
|
v.Set(reflect.ValueOf(value))
|
|
v.Set(reflect.ValueOf(value))
|
|
} else {
|
|
} else {
|
|
- d.saveError(&UnmarshalTypeError{"bool", v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -737,10 +746,10 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
|
}
|
|
}
|
|
switch v.Kind() {
|
|
switch v.Kind() {
|
|
default:
|
|
default:
|
|
- d.saveError(&UnmarshalTypeError{"string", v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
|
|
case reflect.Slice:
|
|
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
|
|
break
|
|
}
|
|
}
|
|
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
|
|
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
|
|
@@ -756,7 +765,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
|
if v.NumMethod() == 0 {
|
|
if v.NumMethod() == 0 {
|
|
v.Set(reflect.ValueOf(string(s)))
|
|
v.Set(reflect.ValueOf(string(s)))
|
|
} else {
|
|
} else {
|
|
- d.saveError(&UnmarshalTypeError{"string", v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -778,7 +787,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
|
if fromQuoted {
|
|
if fromQuoted {
|
|
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
|
|
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
|
|
} else {
|
|
} else {
|
|
- d.error(&UnmarshalTypeError{"number", v.Type()})
|
|
|
|
|
|
+ d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
|
|
}
|
|
}
|
|
case reflect.Interface:
|
|
case reflect.Interface:
|
|
n, err := d.convertNumber(s)
|
|
n, err := d.convertNumber(s)
|
|
@@ -787,7 +796,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
|
break
|
|
break
|
|
}
|
|
}
|
|
if v.NumMethod() != 0 {
|
|
if v.NumMethod() != 0 {
|
|
- d.saveError(&UnmarshalTypeError{"number", v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
|
|
break
|
|
break
|
|
}
|
|
}
|
|
v.Set(reflect.ValueOf(n))
|
|
v.Set(reflect.ValueOf(n))
|
|
@@ -795,7 +804,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
n, err := strconv.ParseInt(s, 10, 64)
|
|
n, err := strconv.ParseInt(s, 10, 64)
|
|
if err != nil || v.OverflowInt(n) {
|
|
if err != nil || v.OverflowInt(n) {
|
|
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
|
|
break
|
|
break
|
|
}
|
|
}
|
|
v.SetInt(n)
|
|
v.SetInt(n)
|
|
@@ -803,7 +812,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:
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
n, err := strconv.ParseUint(s, 10, 64)
|
|
n, err := strconv.ParseUint(s, 10, 64)
|
|
if err != nil || v.OverflowUint(n) {
|
|
if err != nil || v.OverflowUint(n) {
|
|
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
|
|
break
|
|
break
|
|
}
|
|
}
|
|
v.SetUint(n)
|
|
v.SetUint(n)
|
|
@@ -811,7 +820,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
|
case reflect.Float32, reflect.Float64:
|
|
case reflect.Float32, reflect.Float64:
|
|
n, err := strconv.ParseFloat(s, v.Type().Bits())
|
|
n, err := strconv.ParseFloat(s, v.Type().Bits())
|
|
if err != nil || v.OverflowFloat(n) {
|
|
if err != nil || v.OverflowFloat(n) {
|
|
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
|
|
|
|
|
|
+ d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
|
|
break
|
|
break
|
|
}
|
|
}
|
|
v.SetFloat(n)
|
|
v.SetFloat(n)
|