Skip to content

Commit a257ffb

Browse files
xargbradfitz
authored andcommitted
encoding/json: add UnmarshalTypeError.Offset
Fixes #9693 Change-Id: Ibf07199729bfc883b2a7e051cafd98185f912acd Reviewed-on: https://go-review.googlesource.com/3283 Reviewed-by: Russ Cox <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent bd043d8 commit a257ffb

File tree

2 files changed

+22
-21
lines changed

2 files changed

+22
-21
lines changed

src/encoding/json/decode.go

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,9 @@ type Unmarshaler interface {
9090
// An UnmarshalTypeError describes a JSON value that was
9191
// not appropriate for a value of a specific Go type.
9292
type UnmarshalTypeError struct {
93-
Value string // description of JSON value - "bool", "array", "number -5"
94-
Type reflect.Type // type of Go value it could not be assigned to
93+
Value string // description of JSON value - "bool", "array", "number -5"
94+
Type reflect.Type // type of Go value it could not be assigned to
95+
Offset int64 // error occurred after reading Offset bytes
9596
}
9697

9798
func (e *UnmarshalTypeError) Error() string {
@@ -377,7 +378,7 @@ func (d *decodeState) array(v reflect.Value) {
377378
return
378379
}
379380
if ut != nil {
380-
d.saveError(&UnmarshalTypeError{"array", v.Type()})
381+
d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
381382
d.off--
382383
d.next()
383384
return
@@ -396,7 +397,7 @@ func (d *decodeState) array(v reflect.Value) {
396397
// Otherwise it's invalid.
397398
fallthrough
398399
default:
399-
d.saveError(&UnmarshalTypeError{"array", v.Type()})
400+
d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
400401
d.off--
401402
d.next()
402403
return
@@ -485,7 +486,7 @@ func (d *decodeState) object(v reflect.Value) {
485486
return
486487
}
487488
if ut != nil {
488-
d.saveError(&UnmarshalTypeError{"object", v.Type()})
489+
d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
489490
d.off--
490491
d.next() // skip over { } in input
491492
return
@@ -504,7 +505,7 @@ func (d *decodeState) object(v reflect.Value) {
504505
// map must have string kind
505506
t := v.Type()
506507
if t.Key().Kind() != reflect.String {
507-
d.saveError(&UnmarshalTypeError{"object", v.Type()})
508+
d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
508509
d.off--
509510
d.next() // skip over { } in input
510511
return
@@ -515,7 +516,7 @@ func (d *decodeState) object(v reflect.Value) {
515516
case reflect.Struct:
516517

517518
default:
518-
d.saveError(&UnmarshalTypeError{"object", v.Type()})
519+
d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
519520
d.off--
520521
d.next() // skip over { } in input
521522
return
@@ -646,7 +647,7 @@ func (d *decodeState) convertNumber(s string) (interface{}, error) {
646647
}
647648
f, err := strconv.ParseFloat(s, 64)
648649
if err != nil {
649-
return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0)}
650+
return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)}
650651
}
651652
return f, nil
652653
}
@@ -679,7 +680,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
679680
if fromQuoted {
680681
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
681682
} else {
682-
d.saveError(&UnmarshalTypeError{"string", v.Type()})
683+
d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
683684
}
684685
}
685686
s, ok := unquoteBytes(item)
@@ -713,15 +714,15 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
713714
if fromQuoted {
714715
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
715716
} else {
716-
d.saveError(&UnmarshalTypeError{"bool", v.Type()})
717+
d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
717718
}
718719
case reflect.Bool:
719720
v.SetBool(value)
720721
case reflect.Interface:
721722
if v.NumMethod() == 0 {
722723
v.Set(reflect.ValueOf(value))
723724
} else {
724-
d.saveError(&UnmarshalTypeError{"bool", v.Type()})
725+
d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
725726
}
726727
}
727728

@@ -736,10 +737,10 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
736737
}
737738
switch v.Kind() {
738739
default:
739-
d.saveError(&UnmarshalTypeError{"string", v.Type()})
740+
d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
740741
case reflect.Slice:
741742
if v.Type() != byteSliceType {
742-
d.saveError(&UnmarshalTypeError{"string", v.Type()})
743+
d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
743744
break
744745
}
745746
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
@@ -755,7 +756,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
755756
if v.NumMethod() == 0 {
756757
v.Set(reflect.ValueOf(string(s)))
757758
} else {
758-
d.saveError(&UnmarshalTypeError{"string", v.Type()})
759+
d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
759760
}
760761
}
761762

@@ -777,7 +778,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
777778
if fromQuoted {
778779
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
779780
} else {
780-
d.error(&UnmarshalTypeError{"number", v.Type()})
781+
d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
781782
}
782783
case reflect.Interface:
783784
n, err := d.convertNumber(s)
@@ -786,31 +787,31 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
786787
break
787788
}
788789
if v.NumMethod() != 0 {
789-
d.saveError(&UnmarshalTypeError{"number", v.Type()})
790+
d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
790791
break
791792
}
792793
v.Set(reflect.ValueOf(n))
793794

794795
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
795796
n, err := strconv.ParseInt(s, 10, 64)
796797
if err != nil || v.OverflowInt(n) {
797-
d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
798+
d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
798799
break
799800
}
800801
v.SetInt(n)
801802

802803
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
803804
n, err := strconv.ParseUint(s, 10, 64)
804805
if err != nil || v.OverflowUint(n) {
805-
d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
806+
d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
806807
break
807808
}
808809
v.SetUint(n)
809810

810811
case reflect.Float32, reflect.Float64:
811812
n, err := strconv.ParseFloat(s, v.Type().Bits())
812813
if err != nil || v.OverflowFloat(n) {
813-
d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
814+
d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
814815
break
815816
}
816817
v.SetFloat(n)

src/encoding/json/decode_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ var unmarshalTests = []unmarshalTest{
231231
{in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
232232
{in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
233233
{in: "null", ptr: new(interface{}), out: nil},
234-
{in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf("")}},
234+
{in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7}},
235235
{in: `{"x": 1}`, ptr: new(tx), out: tx{}},
236236
{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
237237
{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{
411411
{
412412
in: `{"2009-11-10T23:00:00Z": "hello world"}`,
413413
ptr: &map[time.Time]string{},
414-
err: &UnmarshalTypeError{"object", reflect.TypeOf(map[time.Time]string{})},
414+
err: &UnmarshalTypeError{"object", reflect.TypeOf(map[time.Time]string{}), 1},
415415
},
416416
}
417417

0 commit comments

Comments
 (0)