8
8
package json
9
9
10
10
import (
11
+ "context"
11
12
"encoding"
12
13
"encoding/base64"
13
14
"fmt"
@@ -95,10 +96,15 @@ import (
95
96
// Instead, they are replaced by the Unicode replacement
96
97
// character U+FFFD.
97
98
func Unmarshal (data []byte , v any ) error {
99
+ return UnmarshalContext (context .Background (), data , v )
100
+ }
101
+
102
+ func UnmarshalContext (ctx context.Context , data []byte , v any ) error {
98
103
// Check for well-formedness.
99
104
// Avoids filling out half a data structure
100
105
// before discovering a JSON syntax error.
101
106
var d decodeState
107
+ d .ctx = ctx
102
108
err := checkValid (data , & d .scan )
103
109
if err != nil {
104
110
return err
@@ -209,6 +215,7 @@ type errorContext struct {
209
215
210
216
// decodeState represents the state while decoding a JSON value.
211
217
type decodeState struct {
218
+ ctx context.Context
212
219
data []byte
213
220
off int // next read offset in data
214
221
opcode int // last read result
@@ -428,7 +435,7 @@ func (d *decodeState) valueQuoted() any {
428
435
// If it encounters an Unmarshaler, indirect stops and returns that.
429
436
// If decodingNull is true, indirect stops at the first settable pointer so it
430
437
// can be set to nil.
431
- func indirect (v reflect.Value , decodingNull bool ) (Unmarshaler , encoding.TextUnmarshaler , reflect.Value ) {
438
+ func indirect (v reflect.Value , decodingNull bool ) (Unmarshaler , ContextUnmarshaler , encoding.TextUnmarshaler , reflect.Value ) {
432
439
// Issue #24153 indicates that it is generally not a guaranteed property
433
440
// that you may round-trip a reflect.Value by calling Value.Addr().Elem()
434
441
// and expect the value to still be settable for values derived from
@@ -482,11 +489,14 @@ func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnm
482
489
}
483
490
if v .Type ().NumMethod () > 0 && v .CanInterface () {
484
491
if u , ok := v .Interface ().(Unmarshaler ); ok {
485
- return u , nil , reflect.Value {}
492
+ return u , nil , nil , reflect.Value {}
493
+ }
494
+ if cu , ok := v .Interface ().(ContextUnmarshaler ); ok {
495
+ return nil , cu , nil , reflect.Value {}
486
496
}
487
497
if ! decodingNull {
488
498
if u , ok := v .Interface ().(encoding.TextUnmarshaler ); ok {
489
- return nil , u , reflect.Value {}
499
+ return nil , nil , u , reflect.Value {}
490
500
}
491
501
}
492
502
}
@@ -498,14 +508,14 @@ func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnm
498
508
v = v .Elem ()
499
509
}
500
510
}
501
- return nil , nil , v
511
+ return nil , nil , nil , v
502
512
}
503
513
504
514
// array consumes an array from d.data[d.off-1:], decoding into v.
505
515
// The first byte of the array ('[') has been read already.
506
516
func (d * decodeState ) array (v reflect.Value ) error {
507
517
// Check for unmarshaler.
508
- u , ut , pv := indirect (v , false )
518
+ u , cu , ut , pv := indirect (v , false )
509
519
if u != nil {
510
520
start := d .readIndex ()
511
521
d .skip ()
@@ -515,6 +525,15 @@ func (d *decodeState) array(v reflect.Value) error {
515
525
}
516
526
return nil
517
527
}
528
+ if cu != nil {
529
+ start := d .readIndex ()
530
+ d .skip ()
531
+ err := cu .UnmarshalJSONContext (d .ctx , d .data [start :d .off ])
532
+ if err != nil {
533
+ d .saveError (err )
534
+ }
535
+ return nil
536
+ }
518
537
if ut != nil {
519
538
d .saveError (& UnmarshalTypeError {Value : "array" , Type : v .Type (), Offset : int64 (d .off )})
520
539
d .skip ()
@@ -612,7 +631,7 @@ var (
612
631
// The first byte ('{') of the object has been read already.
613
632
func (d * decodeState ) object (v reflect.Value ) error {
614
633
// Check for unmarshaler.
615
- u , ut , pv := indirect (v , false )
634
+ u , cu , ut , pv := indirect (v , false )
616
635
if u != nil {
617
636
start := d .readIndex ()
618
637
d .skip ()
@@ -622,6 +641,15 @@ func (d *decodeState) object(v reflect.Value) error {
622
641
}
623
642
return nil
624
643
}
644
+ if cu != nil {
645
+ start := d .readIndex ()
646
+ d .skip ()
647
+ err := cu .UnmarshalJSONContext (d .ctx , d .data [start :d .off ])
648
+ if err != nil {
649
+ d .saveError (err )
650
+ }
651
+ return nil
652
+ }
625
653
if ut != nil {
626
654
d .saveError (& UnmarshalTypeError {Value : "object" , Type : v .Type (), Offset : int64 (d .off )})
627
655
d .skip ()
@@ -870,14 +898,21 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
870
898
return nil
871
899
}
872
900
isNull := item [0 ] == 'n' // null
873
- u , ut , pv := indirect (v , isNull )
901
+ u , cu , ut , pv := indirect (v , isNull )
874
902
if u != nil {
875
903
err := u .UnmarshalJSON (item )
876
904
if err != nil {
877
905
d .saveError (err )
878
906
}
879
907
return nil
880
908
}
909
+ if cu != nil {
910
+ err := cu .UnmarshalJSONContext (d .ctx , item )
911
+ if err != nil {
912
+ d .saveError (err )
913
+ }
914
+ return nil
915
+ }
881
916
if ut != nil {
882
917
if item [0 ] != '"' {
883
918
if fromQuoted {
0 commit comments