@@ -359,47 +359,40 @@ func (d *decodeState) scanWhile(op int) int {
359
359
return newOp
360
360
}
361
361
362
+ // discardObject and discardArray are dummy data targets
363
+ // used by the (*decodeState).value method, which
364
+ // accepts a zero reflect.Value to discard a value.
365
+ // The (*decodeState).object and (*decodeState).array methods,
366
+ // however, require a valid reflect.Value destination.
367
+ // These are the target values used when the caller of value
368
+ // wants to skip a field.
369
+ //
370
+ // Because these values refer to zero-sized objects
371
+ // and thus can't be mutated, they're safe for concurrent use
372
+ // by different goroutines unmarshalling skipped fields.
373
+ var (
374
+ discardObject = reflect .ValueOf (struct {}{})
375
+ discardArray = reflect .ValueOf ([0 ]interface {}{})
376
+ )
377
+
362
378
// value decodes a JSON value from d.data[d.off:] into the value.
363
- // it updates d.off to point past the decoded value.
379
+ // It updates d.off to point past the decoded value. If v is
380
+ // invalid, the JSON value is discarded.
364
381
func (d * decodeState ) value (v reflect.Value ) {
365
- if ! v .IsValid () {
366
- _ , rest , err := nextValue (d .data [d .off :], & d .nextscan )
367
- if err != nil {
368
- d .error (err )
369
- }
370
- d .off = len (d .data ) - len (rest )
371
-
372
- // d.scan thinks we're still at the beginning of the item.
373
- // Feed in an empty string - the shortest, simplest value -
374
- // so that it knows we got to the end of the value.
375
- if d .scan .redo {
376
- // rewind.
377
- d .scan .redo = false
378
- d .scan .step = stateBeginValue
379
- }
380
- d .scan .step (& d .scan , '"' )
381
- d .scan .step (& d .scan , '"' )
382
-
383
- n := len (d .scan .parseState )
384
- if n > 0 && d .scan .parseState [n - 1 ] == parseObjectKey {
385
- // d.scan thinks we just read an object key; finish the object
386
- d .scan .step (& d .scan , ':' )
387
- d .scan .step (& d .scan , '"' )
388
- d .scan .step (& d .scan , '"' )
389
- d .scan .step (& d .scan , '}' )
390
- }
391
-
392
- return
393
- }
394
-
395
382
switch op := d .scanWhile (scanSkipSpace ); op {
396
383
default :
397
384
d .error (errPhase )
398
385
399
386
case scanBeginArray :
387
+ if ! v .IsValid () {
388
+ v = discardArray
389
+ }
400
390
d .array (v )
401
391
402
392
case scanBeginObject :
393
+ if ! v .IsValid () {
394
+ v = discardObject
395
+ }
403
396
d .object (v )
404
397
405
398
case scanBeginLiteral :
@@ -517,8 +510,7 @@ func (d *decodeState) array(v reflect.Value) {
517
510
d .off --
518
511
d .next ()
519
512
return
520
- case reflect .Array :
521
- case reflect .Slice :
513
+ case reflect .Array , reflect .Slice :
522
514
break
523
515
}
524
516
@@ -797,7 +789,9 @@ func (d *decodeState) literal(v reflect.Value) {
797
789
d .off --
798
790
d .scan .undo (op )
799
791
800
- d .literalStore (d .data [start :d .off ], v , false )
792
+ if v .IsValid () {
793
+ d .literalStore (d .data [start :d .off ], v , false )
794
+ }
801
795
}
802
796
803
797
// convertNumber converts the number literal s to a float64 or a Number
0 commit comments