Skip to content

Commit 74a92b8

Browse files
pascaldekloebradfitz
authored andcommittedMar 3, 2018
encoding/json: apply conventional error handling in decoder
name old time/op new time/op delta CodeEncoder-12 1.89ms ± 1% 1.91ms ± 0% +1.16% (p=0.000 n=20+19) CodeMarshal-12 2.09ms ± 1% 2.12ms ± 0% +1.63% (p=0.000 n=17+18) CodeDecoder-12 8.43ms ± 1% 8.32ms ± 1% -1.35% (p=0.000 n=18+20) UnicodeDecoder-12 399ns ± 0% 339ns ± 0% -15.00% (p=0.000 n=20+19) DecoderStream-12 281ns ± 1% 231ns ± 0% -17.91% (p=0.000 n=20+16) CodeUnmarshal-12 9.35ms ± 2% 9.15ms ± 2% -2.11% (p=0.000 n=20+20) CodeUnmarshalReuse-12 8.41ms ± 2% 8.29ms ± 2% -1.34% (p=0.000 n=20+20) UnmarshalString-12 81.2ns ± 2% 74.0ns ± 4% -8.89% (p=0.000 n=20+20) UnmarshalFloat64-12 71.1ns ± 2% 64.3ns ± 1% -9.60% (p=0.000 n=20+19) UnmarshalInt64-12 60.6ns ± 2% 53.2ns ± 0% -12.28% (p=0.000 n=18+18) Issue10335-12 96.9ns ± 0% 87.7ns ± 1% -9.52% (p=0.000 n=17+20) Unmapped-12 247ns ± 4% 231ns ± 3% -6.34% (p=0.000 n=20+20) TypeFieldsCache/MissTypes1-12 11.1µs ± 0% 11.1µs ± 0% ~ (p=0.376 n=19+20) TypeFieldsCache/MissTypes10-12 33.9µs ± 0% 33.8µs ± 0% -0.32% (p=0.000 n=18+9) name old speed new speed delta CodeEncoder-12 1.03GB/s ± 1% 1.01GB/s ± 0% -1.15% (p=0.000 n=20+19) CodeMarshal-12 930MB/s ± 1% 915MB/s ± 0% -1.60% (p=0.000 n=17+18) CodeDecoder-12 230MB/s ± 1% 233MB/s ± 1% +1.37% (p=0.000 n=18+20) UnicodeDecoder-12 35.0MB/s ± 0% 41.2MB/s ± 0% +17.60% (p=0.000 n=20+19) CodeUnmarshal-12 208MB/s ± 2% 212MB/s ± 2% +2.16% (p=0.000 n=20+20) name old alloc/op new alloc/op delta Issue10335-12 184B ± 0% 184B ± 0% ~ (all equal) Unmapped-12 216B ± 0% 216B ± 0% ~ (all equal) name old allocs/op new allocs/op delta Issue10335-12 3.00 ± 0% 3.00 ± 0% ~ (all equal) Unmapped-12 4.00 ± 0% 4.00 ± 0% ~ (all equal) Change-Id: I4b1a87a205da2ef9a572f86f85bc833653c61570 Reviewed-on: https://go-review.googlesource.com/98440 Reviewed-by: Brad Fitzpatrick <[email protected]> Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 51b0271 commit 74a92b8

File tree

2 files changed

+132
-107
lines changed

2 files changed

+132
-107
lines changed
 

‎src/encoding/json/decode.go

Lines changed: 127 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -167,22 +167,7 @@ func (e *InvalidUnmarshalError) Error() string {
167167
return "json: Unmarshal(nil " + e.Type.String() + ")"
168168
}
169169

170-
// jsonError is an error wrapper type for internal use only.
171-
// Panics with errors are wrapped in jsonError so that the top-level recover
172-
// can distinguish intentional panics from this package.
173-
type jsonError struct{ error }
174-
175-
func (d *decodeState) unmarshal(v interface{}) (err error) {
176-
defer func() {
177-
if r := recover(); r != nil {
178-
if je, ok := r.(jsonError); ok {
179-
err = je.error
180-
} else {
181-
panic(r)
182-
}
183-
}
184-
}()
185-
170+
func (d *decodeState) unmarshal(v interface{}) error {
186171
rv := reflect.ValueOf(v)
187172
if rv.Kind() != reflect.Ptr || rv.IsNil() {
188173
return &InvalidUnmarshalError{reflect.TypeOf(v)}
@@ -192,7 +177,10 @@ func (d *decodeState) unmarshal(v interface{}) (err error) {
192177
d.scanWhile(scanSkipSpace)
193178
// We decode rv not rv.Elem because the Unmarshaler interface
194179
// test must be applied at the top level of the value.
195-
d.value(rv)
180+
err := d.value(rv)
181+
if err != nil {
182+
return err
183+
}
196184
return d.savedError
197185
}
198186

@@ -306,11 +294,6 @@ func (d *decodeState) init(data []byte) *decodeState {
306294
return d
307295
}
308296

309-
// error aborts the decoding by panicking with err wrapped in jsonError.
310-
func (d *decodeState) error(err error) {
311-
panic(jsonError{d.addErrorContext(err)})
312-
}
313-
314297
// saveError saves the first err it is called with,
315298
// for reporting at the end of the unmarshal.
316299
func (d *decodeState) saveError(err error) {
@@ -380,22 +363,26 @@ func (d *decodeState) scanWhile(op int) {
380363
// value consumes a JSON value from d.data[d.off-1:], decoding into v, and
381364
// reads the following byte ahead. If v is invalid, the value is discarded.
382365
// The first byte of the value has been read already.
383-
func (d *decodeState) value(v reflect.Value) {
366+
func (d *decodeState) value(v reflect.Value) error {
384367
switch d.opcode {
385368
default:
386-
d.error(errPhase)
369+
return errPhase
387370

388371
case scanBeginArray:
389372
if v.IsValid() {
390-
d.array(v)
373+
if err := d.array(v); err != nil {
374+
return err
375+
}
391376
} else {
392377
d.skip()
393378
}
394379
d.scanNext()
395380

396381
case scanBeginObject:
397382
if v.IsValid() {
398-
d.object(v)
383+
if err := d.object(v); err != nil {
384+
return err
385+
}
399386
} else {
400387
d.skip()
401388
}
@@ -407,9 +394,12 @@ func (d *decodeState) value(v reflect.Value) {
407394
d.scanWhile(scanContinue)
408395

409396
if v.IsValid() {
410-
d.literalStore(d.data[start:d.readIndex()], v, false)
397+
if err := d.literalStore(d.data[start:d.readIndex()], v, false); err != nil {
398+
return err
399+
}
411400
}
412401
}
402+
return nil
413403
}
414404

415405
type unquotedValue struct{}
@@ -418,10 +408,10 @@ type unquotedValue struct{}
418408
// quoted string literal or literal null into an interface value.
419409
// If it finds anything other than a quoted string literal or null,
420410
// valueQuoted returns unquotedValue{}.
421-
func (d *decodeState) valueQuoted() interface{} {
411+
func (d *decodeState) valueQuoted() (interface{}, error) {
422412
switch d.opcode {
423413
default:
424-
d.error(errPhase)
414+
return nil, errPhase
425415

426416
case scanBeginArray:
427417
d.skip()
@@ -432,12 +422,16 @@ func (d *decodeState) valueQuoted() interface{} {
432422
d.scanNext()
433423

434424
case scanBeginLiteral:
435-
switch v := d.literalInterface().(type) {
425+
v, err := d.literalInterface()
426+
if err != nil {
427+
return nil, err
428+
}
429+
switch v.(type) {
436430
case nil, string:
437-
return v
431+
return v, nil
438432
}
439433
}
440-
return unquotedValue{}
434+
return unquotedValue{}, nil
441435
}
442436

443437
// indirect walks down v allocating pointers as needed,
@@ -511,22 +505,18 @@ func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnm
511505

512506
// array consumes an array from d.data[d.off-1:], decoding into v.
513507
// The first byte of the array ('[') has been read already.
514-
func (d *decodeState) array(v reflect.Value) {
508+
func (d *decodeState) array(v reflect.Value) error {
515509
// Check for unmarshaler.
516510
u, ut, pv := indirect(v, false)
517511
if u != nil {
518512
start := d.readIndex()
519513
d.skip()
520-
err := u.UnmarshalJSON(d.data[start:d.off])
521-
if err != nil {
522-
d.error(err)
523-
}
524-
return
514+
return u.UnmarshalJSON(d.data[start:d.off])
525515
}
526516
if ut != nil {
527517
d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
528518
d.skip()
529-
return
519+
return nil
530520
}
531521
v = pv
532522

@@ -535,15 +525,19 @@ func (d *decodeState) array(v reflect.Value) {
535525
case reflect.Interface:
536526
if v.NumMethod() == 0 {
537527
// Decoding into nil interface? Switch to non-reflect code.
538-
v.Set(reflect.ValueOf(d.arrayInterface()))
539-
return
528+
ai, err := d.arrayInterface()
529+
if err != nil {
530+
return err
531+
}
532+
v.Set(reflect.ValueOf(ai))
533+
return nil
540534
}
541535
// Otherwise it's invalid.
542536
fallthrough
543537
default:
544538
d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
545539
d.skip()
546-
return
540+
return nil
547541
case reflect.Array:
548542
case reflect.Slice:
549543
break
@@ -576,10 +570,14 @@ func (d *decodeState) array(v reflect.Value) {
576570

577571
if i < v.Len() {
578572
// Decode into element.
579-
d.value(v.Index(i))
573+
if err := d.value(v.Index(i)); err != nil {
574+
return err
575+
}
580576
} else {
581577
// Ran out of fixed array: skip.
582-
d.value(reflect.Value{})
578+
if err := d.value(reflect.Value{}); err != nil {
579+
return err
580+
}
583581
}
584582
i++
585583

@@ -591,7 +589,7 @@ func (d *decodeState) array(v reflect.Value) {
591589
break
592590
}
593591
if d.opcode != scanArrayValue {
594-
d.error(errPhase)
592+
return errPhase
595593
}
596594
}
597595

@@ -609,36 +607,37 @@ func (d *decodeState) array(v reflect.Value) {
609607
if i == 0 && v.Kind() == reflect.Slice {
610608
v.Set(reflect.MakeSlice(v.Type(), 0, 0))
611609
}
610+
return nil
612611
}
613612

614613
var nullLiteral = []byte("null")
615614
var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
616615

617616
// object consumes an object from d.data[d.off-1:], decoding into v.
618617
// The first byte ('{') of the object has been read already.
619-
func (d *decodeState) object(v reflect.Value) {
618+
func (d *decodeState) object(v reflect.Value) error {
620619
// Check for unmarshaler.
621620
u, ut, pv := indirect(v, false)
622621
if u != nil {
623622
start := d.readIndex()
624623
d.skip()
625-
err := u.UnmarshalJSON(d.data[start:d.off])
626-
if err != nil {
627-
d.error(err)
628-
}
629-
return
624+
return u.UnmarshalJSON(d.data[start:d.off])
630625
}
631626
if ut != nil {
632627
d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)})
633628
d.skip()
634-
return
629+
return nil
635630
}
636631
v = pv
637632

638633
// Decoding into nil interface? Switch to non-reflect code.
639634
if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
640-
v.Set(reflect.ValueOf(d.objectInterface()))
641-
return
635+
oi, err := d.objectInterface()
636+
if err != nil {
637+
return err
638+
}
639+
v.Set(reflect.ValueOf(oi))
640+
return nil
642641
}
643642

644643
// Check type of target:
@@ -658,7 +657,7 @@ func (d *decodeState) object(v reflect.Value) {
658657
if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) {
659658
d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)})
660659
d.skip()
661-
return
660+
return nil
662661
}
663662
}
664663
if v.IsNil() {
@@ -669,7 +668,7 @@ func (d *decodeState) object(v reflect.Value) {
669668
default:
670669
d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)})
671670
d.skip()
672-
return
671+
return nil
673672
}
674673

675674
var mapElem reflect.Value
@@ -682,7 +681,7 @@ func (d *decodeState) object(v reflect.Value) {
682681
break
683682
}
684683
if d.opcode != scanBeginLiteral {
685-
d.error(errPhase)
684+
return errPhase
686685
}
687686

688687
// Read key.
@@ -691,7 +690,7 @@ func (d *decodeState) object(v reflect.Value) {
691690
item := d.data[start:d.readIndex()]
692691
key, ok := unquoteBytes(item)
693692
if !ok {
694-
d.error(errPhase)
693+
return errPhase
695694
}
696695

697696
// Figure out field corresponding to key.
@@ -756,21 +755,31 @@ func (d *decodeState) object(v reflect.Value) {
756755
d.scanWhile(scanSkipSpace)
757756
}
758757
if d.opcode != scanObjectKey {
759-
d.error(errPhase)
758+
return errPhase
760759
}
761760
d.scanWhile(scanSkipSpace)
762761

763762
if destring {
764-
switch qv := d.valueQuoted().(type) {
763+
q, err := d.valueQuoted()
764+
if err != nil {
765+
return err
766+
}
767+
switch qv := q.(type) {
765768
case nil:
766-
d.literalStore(nullLiteral, subv, false)
769+
if err := d.literalStore(nullLiteral, subv, false); err != nil {
770+
return err
771+
}
767772
case string:
768-
d.literalStore([]byte(qv), subv, true)
773+
if err := d.literalStore([]byte(qv), subv, true); err != nil {
774+
return err
775+
}
769776
default:
770777
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type()))
771778
}
772779
} else {
773-
d.value(subv)
780+
if err := d.value(subv); err != nil {
781+
return err
782+
}
774783
}
775784

776785
// Write value back to map;
@@ -783,7 +792,9 @@ func (d *decodeState) object(v reflect.Value) {
783792
kv = reflect.ValueOf(key).Convert(kt)
784793
case reflect.PtrTo(kt).Implements(textUnmarshalerType):
785794
kv = reflect.New(v.Type().Key())
786-
d.literalStore(item, kv, true)
795+
if err := d.literalStore(item, kv, true); err != nil {
796+
return err
797+
}
787798
kv = kv.Elem()
788799
default:
789800
switch kt.Kind() {
@@ -792,15 +803,15 @@ func (d *decodeState) object(v reflect.Value) {
792803
n, err := strconv.ParseInt(s, 10, 64)
793804
if err != nil || reflect.Zero(kt).OverflowInt(n) {
794805
d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
795-
return
806+
return nil
796807
}
797808
kv = reflect.ValueOf(n).Convert(kt)
798809
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
799810
s := string(key)
800811
n, err := strconv.ParseUint(s, 10, 64)
801812
if err != nil || reflect.Zero(kt).OverflowUint(n) {
802813
d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
803-
return
814+
return nil
804815
}
805816
kv = reflect.ValueOf(n).Convert(kt)
806817
default:
@@ -818,12 +829,13 @@ func (d *decodeState) object(v reflect.Value) {
818829
break
819830
}
820831
if d.opcode != scanObjectValue {
821-
d.error(errPhase)
832+
return errPhase
822833
}
823834

824835
d.errorContext.Struct = ""
825836
d.errorContext.Field = ""
826837
}
838+
return nil
827839
}
828840

829841
// convertNumber converts the number literal s to a float64 or a Number
@@ -846,21 +858,21 @@ var numberType = reflect.TypeOf(Number(""))
846858
// fromQuoted indicates whether this literal came from unwrapping a
847859
// string from the ",string" struct tag option. this is used only to
848860
// produce more helpful error messages.
849-
func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) {
861+
func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) error {
850862
// Check for unmarshaler.
851863
if len(item) == 0 {
852864
//Empty string given
853865
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
854-
return
866+
return nil
855867
}
856868
isNull := item[0] == 'n' // null
857869
u, ut, pv := indirect(v, isNull)
858870
if u != nil {
859871
err := u.UnmarshalJSON(item)
860872
if err != nil {
861-
d.error(err)
873+
return err
862874
}
863-
return
875+
return nil
864876
}
865877
if ut != nil {
866878
if item[0] != '"' {
@@ -878,21 +890,21 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
878890
}
879891
d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())})
880892
}
881-
return
893+
return nil
882894
}
883895
s, ok := unquoteBytes(item)
884896
if !ok {
885897
if fromQuoted {
886-
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
898+
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
887899
} else {
888-
d.error(errPhase)
900+
return errPhase
889901
}
890902
}
891903
err := ut.UnmarshalText(s)
892904
if err != nil {
893-
d.error(err)
905+
return err
894906
}
895-
return
907+
return nil
896908
}
897909

898910
v = pv
@@ -939,9 +951,9 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
939951
s, ok := unquoteBytes(item)
940952
if !ok {
941953
if fromQuoted {
942-
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
954+
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
943955
} else {
944-
d.error(errPhase)
956+
return errPhase
945957
}
946958
}
947959
switch v.Kind() {
@@ -972,9 +984,9 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
972984
default: // number
973985
if c != '-' && (c < '0' || c > '9') {
974986
if fromQuoted {
975-
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
987+
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
976988
} else {
977-
d.error(errPhase)
989+
return errPhase
978990
}
979991
}
980992
s := string(item)
@@ -983,14 +995,14 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
983995
if v.Kind() == reflect.String && v.Type() == numberType {
984996
v.SetString(s)
985997
if !isValidNumber(s) {
986-
d.error(fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item))
998+
return fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item)
987999
}
9881000
break
9891001
}
9901002
if fromQuoted {
991-
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
1003+
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
9921004
} else {
993-
d.error(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
1005+
return &UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}
9941006
}
9951007
case reflect.Interface:
9961008
n, err := d.convertNumber(s)
@@ -1029,32 +1041,32 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
10291041
v.SetFloat(n)
10301042
}
10311043
}
1044+
return nil
10321045
}
10331046

10341047
// The xxxInterface routines build up a value to be stored
10351048
// in an empty interface. They are not strictly necessary,
10361049
// but they avoid the weight of reflection in this common case.
10371050

10381051
// valueInterface is like value but returns interface{}
1039-
func (d *decodeState) valueInterface() (val interface{}) {
1052+
func (d *decodeState) valueInterface() (val interface{}, err error) {
10401053
switch d.opcode {
10411054
default:
1042-
d.error(errPhase)
1043-
panic("unreachable")
1055+
err = errPhase
10441056
case scanBeginArray:
1045-
val = d.arrayInterface()
1057+
val, err = d.arrayInterface()
10461058
d.scanNext()
10471059
case scanBeginObject:
1048-
val = d.objectInterface()
1060+
val, err = d.objectInterface()
10491061
d.scanNext()
10501062
case scanBeginLiteral:
1051-
val = d.literalInterface()
1063+
val, err = d.literalInterface()
10521064
}
10531065
return
10541066
}
10551067

10561068
// arrayInterface is like array but returns []interface{}.
1057-
func (d *decodeState) arrayInterface() []interface{} {
1069+
func (d *decodeState) arrayInterface() ([]interface{}, error) {
10581070
var v = make([]interface{}, 0)
10591071
for {
10601072
// Look ahead for ] - can only happen on first iteration.
@@ -1063,7 +1075,11 @@ func (d *decodeState) arrayInterface() []interface{} {
10631075
break
10641076
}
10651077

1066-
v = append(v, d.valueInterface())
1078+
vi, err := d.valueInterface()
1079+
if err != nil {
1080+
return nil, err
1081+
}
1082+
v = append(v, vi)
10671083

10681084
// Next token must be , or ].
10691085
if d.opcode == scanSkipSpace {
@@ -1073,14 +1089,14 @@ func (d *decodeState) arrayInterface() []interface{} {
10731089
break
10741090
}
10751091
if d.opcode != scanArrayValue {
1076-
d.error(errPhase)
1092+
return nil, errPhase
10771093
}
10781094
}
1079-
return v
1095+
return v, nil
10801096
}
10811097

10821098
// objectInterface is like object but returns map[string]interface{}.
1083-
func (d *decodeState) objectInterface() map[string]interface{} {
1099+
func (d *decodeState) objectInterface() (map[string]interface{}, error) {
10841100
m := make(map[string]interface{})
10851101
for {
10861102
// Read opening " of string key or closing }.
@@ -1090,7 +1106,7 @@ func (d *decodeState) objectInterface() map[string]interface{} {
10901106
break
10911107
}
10921108
if d.opcode != scanBeginLiteral {
1093-
d.error(errPhase)
1109+
return nil, errPhase
10941110
}
10951111

10961112
// Read string key.
@@ -1099,20 +1115,24 @@ func (d *decodeState) objectInterface() map[string]interface{} {
10991115
item := d.data[start:d.readIndex()]
11001116
key, ok := unquote(item)
11011117
if !ok {
1102-
d.error(errPhase)
1118+
return nil, errPhase
11031119
}
11041120

11051121
// Read : before value.
11061122
if d.opcode == scanSkipSpace {
11071123
d.scanWhile(scanSkipSpace)
11081124
}
11091125
if d.opcode != scanObjectKey {
1110-
d.error(errPhase)
1126+
return nil, errPhase
11111127
}
11121128
d.scanWhile(scanSkipSpace)
11131129

11141130
// Read value.
1115-
m[key] = d.valueInterface()
1131+
vi, err := d.valueInterface()
1132+
if err != nil {
1133+
return nil, err
1134+
}
1135+
m[key] = vi
11161136

11171137
// Next token must be , or }.
11181138
if d.opcode == scanSkipSpace {
@@ -1122,16 +1142,16 @@ func (d *decodeState) objectInterface() map[string]interface{} {
11221142
break
11231143
}
11241144
if d.opcode != scanObjectValue {
1125-
d.error(errPhase)
1145+
return nil, errPhase
11261146
}
11271147
}
1128-
return m
1148+
return m, nil
11291149
}
11301150

11311151
// literalInterface consumes and returns a literal from d.data[d.off-1:] and
11321152
// it reads the following byte ahead. The first byte of the literal has been
11331153
// read already (that's how the caller knows it's a literal).
1134-
func (d *decodeState) literalInterface() interface{} {
1154+
func (d *decodeState) literalInterface() (interface{}, error) {
11351155
// All bytes inside literal return scanContinue op code.
11361156
start := d.readIndex()
11371157
d.scanWhile(scanContinue)
@@ -1140,27 +1160,27 @@ func (d *decodeState) literalInterface() interface{} {
11401160

11411161
switch c := item[0]; c {
11421162
case 'n': // null
1143-
return nil
1163+
return nil, nil
11441164

11451165
case 't', 'f': // true, false
1146-
return c == 't'
1166+
return c == 't', nil
11471167

11481168
case '"': // string
11491169
s, ok := unquote(item)
11501170
if !ok {
1151-
d.error(errPhase)
1171+
return nil, errPhase
11521172
}
1153-
return s
1173+
return s, nil
11541174

11551175
default: // number
11561176
if c != '-' && (c < '0' || c > '9') {
1157-
d.error(errPhase)
1177+
return nil, errPhase
11581178
}
11591179
n, err := d.convertNumber(string(item))
11601180
if err != nil {
11611181
d.saveError(err)
11621182
}
1163-
return n
1183+
return n, nil
11641184
}
11651185
}
11661186

‎src/encoding/json/encode.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,11 @@ func newEncodeState() *encodeState {
281281
return new(encodeState)
282282
}
283283

284+
// jsonError is an error wrapper type for internal use only.
285+
// Panics with errors are wrapped in jsonError so that the top-level recover
286+
// can distinguish intentional panics from this package.
287+
type jsonError struct{ error }
288+
284289
func (e *encodeState) marshal(v interface{}, opts encOpts) (err error) {
285290
defer func() {
286291
if r := recover(); r != nil {

0 commit comments

Comments
 (0)
Please sign in to comment.