mirror of
https://github.com/golang/go
synced 2024-11-18 16:14:46 -07:00
encoding/json: add UnmarshalTypeError.Offset
Fixes #9693 Change-Id: Ibf07199729bfc883b2a7e051cafd98185f912acd Reviewed-on: https://go-review.googlesource.com/3283 Reviewed-by: Russ Cox <rsc@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
bd043d8629
commit
a257ffb178
@ -90,8 +90,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 +378,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 +397,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 +486,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 +505,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 +516,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
|
||||
@ -646,7 +647,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,7 +680,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{"string", v.Type()})
|
||||
d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
|
||||
}
|
||||
}
|
||||
s, ok := unquoteBytes(item)
|
||||
@ -713,7 +714,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 +722,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 +737,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()})
|
||||
d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
|
||||
break
|
||||
}
|
||||
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
|
||||
@ -755,7 +756,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 +778,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 +787,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 +795,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 +803,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 +811,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)
|
||||
|
@ -231,7 +231,7 @@ var unmarshalTests = []unmarshalTest{
|
||||
{in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
|
||||
{in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
|
||||
{in: "null", ptr: new(interface{}), out: nil},
|
||||
{in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf("")}},
|
||||
{in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7}},
|
||||
{in: `{"x": 1}`, ptr: new(tx), out: tx{}},
|
||||
{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
|
||||
{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true},
|
||||
@ -411,7 +411,7 @@ var unmarshalTests = []unmarshalTest{
|
||||
{
|
||||
in: `{"2009-11-10T23:00:00Z": "hello world"}`,
|
||||
ptr: &map[time.Time]string{},
|
||||
err: &UnmarshalTypeError{"object", reflect.TypeOf(map[time.Time]string{})},
|
||||
err: &UnmarshalTypeError{"object", reflect.TypeOf(map[time.Time]string{}), 1},
|
||||
},
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user