@@ -112,9 +112,14 @@ type UnmarshalTypeError struct {
112
112
Value string // description of JSON value - "bool", "array", "number -5"
113
113
Type reflect.Type // type of Go value it could not be assigned to
114
114
Offset int64 // error occurred after reading Offset bytes
115
+ Struct string // name of the struct type containing the field
116
+ Field string // name of the field holding the Go value
115
117
}
116
118
117
119
func (e * UnmarshalTypeError ) Error () string {
120
+ if e .Struct != "" || e .Field != "" {
121
+ return "json: cannot unmarshal " + e .Value + " into Go struct field " + e .Struct + "." + e .Field + " of type " + e .Type .String ()
122
+ }
118
123
return "json: cannot unmarshal " + e .Value + " into Go value of type " + e .Type .String ()
119
124
}
120
125
@@ -248,10 +253,14 @@ func isValidNumber(s string) bool {
248
253
249
254
// decodeState represents the state while decoding a JSON value.
250
255
type decodeState struct {
251
- data []byte
252
- off int // read offset in data
253
- scan scanner
254
- nextscan scanner // for calls to nextValue
256
+ data []byte
257
+ off int // read offset in data
258
+ scan scanner
259
+ nextscan scanner // for calls to nextValue
260
+ errorContext struct { // provides context for type errors
261
+ Struct string
262
+ Field string
263
+ }
255
264
savedError error
256
265
useNumber bool
257
266
}
@@ -265,22 +274,37 @@ func (d *decodeState) init(data []byte) *decodeState {
265
274
d .data = data
266
275
d .off = 0
267
276
d .savedError = nil
277
+ d .errorContext .Struct = ""
278
+ d .errorContext .Field = ""
268
279
return d
269
280
}
270
281
271
282
// error aborts the decoding by panicking with err.
272
283
func (d * decodeState ) error (err error ) {
273
- panic (err )
284
+ panic (d . addErrorContext ( err ) )
274
285
}
275
286
276
287
// saveError saves the first err it is called with,
277
288
// for reporting at the end of the unmarshal.
278
289
func (d * decodeState ) saveError (err error ) {
279
290
if d .savedError == nil {
280
- d .savedError = err
291
+ d .savedError = d . addErrorContext ( err )
281
292
}
282
293
}
283
294
295
+ // addErrorContext returns a new error enhanced with information from d.errorContext
296
+ func (d * decodeState ) addErrorContext (err error ) error {
297
+ if d .errorContext .Struct != "" || d .errorContext .Field != "" {
298
+ switch err := err .(type ) {
299
+ case * UnmarshalTypeError :
300
+ err .Struct = d .errorContext .Struct
301
+ err .Field = d .errorContext .Field
302
+ return err
303
+ }
304
+ }
305
+ return err
306
+ }
307
+
284
308
// next cuts off and returns the next full JSON value in d.data[d.off:].
285
309
// The next value is known to be an object or array, not a literal.
286
310
func (d * decodeState ) next () []byte {
@@ -457,7 +481,7 @@ func (d *decodeState) array(v reflect.Value) {
457
481
return
458
482
}
459
483
if ut != nil {
460
- d .saveError (& UnmarshalTypeError {"array" , v .Type (), int64 (d .off )})
484
+ d .saveError (& UnmarshalTypeError {Value : "array" , Type : v .Type (), Offset : int64 (d .off )})
461
485
d .off --
462
486
d .next ()
463
487
return
@@ -476,7 +500,7 @@ func (d *decodeState) array(v reflect.Value) {
476
500
// Otherwise it's invalid.
477
501
fallthrough
478
502
default :
479
- d .saveError (& UnmarshalTypeError {"array" , v .Type (), int64 (d .off )})
503
+ d .saveError (& UnmarshalTypeError {Value : "array" , Type : v .Type (), Offset : int64 (d .off )})
480
504
d .off --
481
505
d .next ()
482
506
return
@@ -566,7 +590,7 @@ func (d *decodeState) object(v reflect.Value) {
566
590
return
567
591
}
568
592
if ut != nil {
569
- d .saveError (& UnmarshalTypeError {"object" , v .Type (), int64 (d .off )})
593
+ d .saveError (& UnmarshalTypeError {Value : "object" , Type : v .Type (), Offset : int64 (d .off )})
570
594
d .off --
571
595
d .next () // skip over { } in input
572
596
return
@@ -594,7 +618,7 @@ func (d *decodeState) object(v reflect.Value) {
594
618
reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 , reflect .Uintptr :
595
619
default :
596
620
if ! reflect .PtrTo (t .Key ()).Implements (textUnmarshalerType ) {
597
- d .saveError (& UnmarshalTypeError {"object" , v .Type (), int64 (d .off )})
621
+ d .saveError (& UnmarshalTypeError {Value : "object" , Type : v .Type (), Offset : int64 (d .off )})
598
622
d .off --
599
623
d .next () // skip over { } in input
600
624
return
@@ -604,9 +628,9 @@ func (d *decodeState) object(v reflect.Value) {
604
628
v .Set (reflect .MakeMap (t ))
605
629
}
606
630
case reflect .Struct :
607
-
631
+ // ok
608
632
default :
609
- d .saveError (& UnmarshalTypeError {"object" , v .Type (), int64 (d .off )})
633
+ d .saveError (& UnmarshalTypeError {Value : "object" , Type : v .Type (), Offset : int64 (d .off )})
610
634
d .off --
611
635
d .next () // skip over { } in input
612
636
return
@@ -671,6 +695,8 @@ func (d *decodeState) object(v reflect.Value) {
671
695
}
672
696
subv = subv .Field (i )
673
697
}
698
+ d .errorContext .Field = f .name
699
+ d .errorContext .Struct = v .Type ().Name ()
674
700
}
675
701
}
676
702
@@ -682,7 +708,6 @@ func (d *decodeState) object(v reflect.Value) {
682
708
d .error (errPhase )
683
709
}
684
710
685
- // Read value.
686
711
if destring {
687
712
switch qv := d .valueQuoted ().(type ) {
688
713
case nil :
@@ -714,15 +739,15 @@ func (d *decodeState) object(v reflect.Value) {
714
739
s := string (key )
715
740
n , err := strconv .ParseInt (s , 10 , 64 )
716
741
if err != nil || reflect .Zero (kt ).OverflowInt (n ) {
717
- d .saveError (& UnmarshalTypeError {"number " + s , kt , int64 (start + 1 )})
742
+ d .saveError (& UnmarshalTypeError {Value : "number " + s , Type : kt , Offset : int64 (start + 1 )})
718
743
return
719
744
}
720
745
kv = reflect .ValueOf (n ).Convert (kt )
721
746
case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 , reflect .Uintptr :
722
747
s := string (key )
723
748
n , err := strconv .ParseUint (s , 10 , 64 )
724
749
if err != nil || reflect .Zero (kt ).OverflowUint (n ) {
725
- d .saveError (& UnmarshalTypeError {"number " + s , kt , int64 (start + 1 )})
750
+ d .saveError (& UnmarshalTypeError {Value : "number " + s , Type : kt , Offset : int64 (start + 1 )})
726
751
return
727
752
}
728
753
kv = reflect .ValueOf (n ).Convert (kt )
@@ -741,6 +766,9 @@ func (d *decodeState) object(v reflect.Value) {
741
766
if op != scanObjectValue {
742
767
d .error (errPhase )
743
768
}
769
+
770
+ d .errorContext .Struct = ""
771
+ d .errorContext .Field = ""
744
772
}
745
773
}
746
774
@@ -767,7 +795,7 @@ func (d *decodeState) convertNumber(s string) (interface{}, error) {
767
795
}
768
796
f , err := strconv .ParseFloat (s , 64 )
769
797
if err != nil {
770
- return nil , & UnmarshalTypeError {"number " + s , reflect .TypeOf (0.0 ), int64 (d .off )}
798
+ return nil , & UnmarshalTypeError {Value : "number " + s , Type : reflect .TypeOf (0.0 ), Offset : int64 (d .off )}
771
799
}
772
800
return f , nil
773
801
}
@@ -800,7 +828,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
800
828
if fromQuoted {
801
829
d .saveError (fmt .Errorf ("json: invalid use of ,string struct tag, trying to unmarshal %q into %v" , item , v .Type ()))
802
830
} else {
803
- d .saveError (& UnmarshalTypeError {"string" , v .Type (), int64 (d .off )})
831
+ d .saveError (& UnmarshalTypeError {Value : "string" , Type : v .Type (), Offset : int64 (d .off )})
804
832
}
805
833
return
806
834
}
@@ -835,15 +863,15 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
835
863
if fromQuoted {
836
864
d .saveError (fmt .Errorf ("json: invalid use of ,string struct tag, trying to unmarshal %q into %v" , item , v .Type ()))
837
865
} else {
838
- d .saveError (& UnmarshalTypeError {"bool" , v .Type (), int64 (d .off )})
866
+ d .saveError (& UnmarshalTypeError {Value : "bool" , Type : v .Type (), Offset : int64 (d .off )})
839
867
}
840
868
case reflect .Bool :
841
869
v .SetBool (value )
842
870
case reflect .Interface :
843
871
if v .NumMethod () == 0 {
844
872
v .Set (reflect .ValueOf (value ))
845
873
} else {
846
- d .saveError (& UnmarshalTypeError {"bool" , v .Type (), int64 (d .off )})
874
+ d .saveError (& UnmarshalTypeError {Value : "bool" , Type : v .Type (), Offset : int64 (d .off )})
847
875
}
848
876
}
849
877
@@ -858,10 +886,10 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
858
886
}
859
887
switch v .Kind () {
860
888
default :
861
- d .saveError (& UnmarshalTypeError {"string" , v .Type (), int64 (d .off )})
889
+ d .saveError (& UnmarshalTypeError {Value : "string" , Type : v .Type (), Offset : int64 (d .off )})
862
890
case reflect .Slice :
863
891
if v .Type ().Elem ().Kind () != reflect .Uint8 {
864
- d .saveError (& UnmarshalTypeError {"string" , v .Type (), int64 (d .off )})
892
+ d .saveError (& UnmarshalTypeError {Value : "string" , Type : v .Type (), Offset : int64 (d .off )})
865
893
break
866
894
}
867
895
b := make ([]byte , base64 .StdEncoding .DecodedLen (len (s )))
@@ -877,7 +905,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
877
905
if v .NumMethod () == 0 {
878
906
v .Set (reflect .ValueOf (string (s )))
879
907
} else {
880
- d .saveError (& UnmarshalTypeError {"string" , v .Type (), int64 (d .off )})
908
+ d .saveError (& UnmarshalTypeError {Value : "string" , Type : v .Type (), Offset : int64 (d .off )})
881
909
}
882
910
}
883
911
@@ -902,7 +930,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
902
930
if fromQuoted {
903
931
d .error (fmt .Errorf ("json: invalid use of ,string struct tag, trying to unmarshal %q into %v" , item , v .Type ()))
904
932
} else {
905
- d .error (& UnmarshalTypeError {"number" , v .Type (), int64 (d .off )})
933
+ d .error (& UnmarshalTypeError {Value : "number" , Type : v .Type (), Offset : int64 (d .off )})
906
934
}
907
935
case reflect .Interface :
908
936
n , err := d .convertNumber (s )
@@ -911,31 +939,31 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
911
939
break
912
940
}
913
941
if v .NumMethod () != 0 {
914
- d .saveError (& UnmarshalTypeError {"number" , v .Type (), int64 (d .off )})
942
+ d .saveError (& UnmarshalTypeError {Value : "number" , Type : v .Type (), Offset : int64 (d .off )})
915
943
break
916
944
}
917
945
v .Set (reflect .ValueOf (n ))
918
946
919
947
case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
920
948
n , err := strconv .ParseInt (s , 10 , 64 )
921
949
if err != nil || v .OverflowInt (n ) {
922
- d .saveError (& UnmarshalTypeError {"number " + s , v .Type (), int64 (d .off )})
950
+ d .saveError (& UnmarshalTypeError {Value : "number " + s , Type : v .Type (), Offset : int64 (d .off )})
923
951
break
924
952
}
925
953
v .SetInt (n )
926
954
927
955
case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 , reflect .Uintptr :
928
956
n , err := strconv .ParseUint (s , 10 , 64 )
929
957
if err != nil || v .OverflowUint (n ) {
930
- d .saveError (& UnmarshalTypeError {"number " + s , v .Type (), int64 (d .off )})
958
+ d .saveError (& UnmarshalTypeError {Value : "number " + s , Type : v .Type (), Offset : int64 (d .off )})
931
959
break
932
960
}
933
961
v .SetUint (n )
934
962
935
963
case reflect .Float32 , reflect .Float64 :
936
964
n , err := strconv .ParseFloat (s , v .Type ().Bits ())
937
965
if err != nil || v .OverflowFloat (n ) {
938
- d .saveError (& UnmarshalTypeError {"number " + s , v .Type (), int64 (d .off )})
966
+ d .saveError (& UnmarshalTypeError {Value : "number " + s , Type : v .Type (), Offset : int64 (d .off )})
939
967
break
940
968
}
941
969
v .SetFloat (n )
0 commit comments