diff --git a/src/encoding/json/stream.go b/src/encoding/json/stream.go index 5c98d1de049..78ec63673c1 100644 --- a/src/encoding/json/stream.go +++ b/src/encoding/json/stream.go @@ -12,13 +12,14 @@ import ( // A Decoder reads and decodes JSON values from an input stream. type Decoder struct { - r io.Reader - buf []byte - d decodeState - scanp int // start of unread data in buf - scanned int64 // amount of data already scanned - scan scanner - err error + r io.Reader + buf []byte + d decodeState + scanp int // start of unread data in buf + scanned int64 // amount of data already scanned + scan scanner + err error + errFromMore bool tokenState int tokenStack []int @@ -48,7 +49,12 @@ func (dec *Decoder) DisallowUnknownFields() { dec.d.disallowUnknownFields = true // the conversion of JSON into a Go value. func (dec *Decoder) Decode(v any) error { if dec.err != nil { - return dec.err + err := dec.err + if dec.errFromMore { + dec.err = nil + dec.errFromMore = false + } + return err } if err := dec.tokenPrepareForDecode(); err != nil { @@ -365,6 +371,13 @@ func (d Delim) String() string { // to mark the start and end of arrays and objects. // Commas and colons are elided. func (dec *Decoder) Token() (Token, error) { + if dec.err != nil && dec.errFromMore { + err := dec.err + dec.err = nil + dec.errFromMore = false + return nil, err + } + for { c, err := dec.peek() if err != nil { @@ -481,7 +494,17 @@ func (dec *Decoder) tokenError(c byte) (Token, error) { // current array or object being parsed. func (dec *Decoder) More() bool { c, err := dec.peek() - return err == nil && c != ']' && c != '}' + if err != nil { + if err == io.EOF { + dec.err = nil + dec.errFromMore = false + return false + } + dec.err = err + dec.errFromMore = true + return true + } + return c != ']' && c != '}' } func (dec *Decoder) peek() (byte, error) { diff --git a/src/encoding/json/stream_test.go b/src/encoding/json/stream_test.go index 32ede8cc7e6..e9b61cdc82d 100644 --- a/src/encoding/json/stream_test.go +++ b/src/encoding/json/stream_test.go @@ -6,6 +6,7 @@ package json import ( "bytes" + "errors" "fmt" "io" "log" @@ -520,3 +521,64 @@ func TestHTTPDecoding(t *testing.T) { t.Errorf("Decode error:\n\tgot: %v\n\twant: io.EOF", err) } } + +type failingDecoderTestReader struct { + t *testing.T + i int + err error +} + +func (c *failingDecoderTestReader) Read(b []byte) (n int, err error) { + i := c.i + c.i++ + + defer func() { + c.t.Logf("%v, %v, %v, %v\n", i, len(b), n, err) + + // Decoder always passes a buffer with size that has at least 512 Bytes. This test + // depends on that behaviour, so that the reader does not get unnecessarily complicated. + if len(b) == n { + c.t.Fatal("small buffer passed to Read") + } + }() + + switch i { + case 0: + return copy(b, `[{ "test": 1 }`), nil + case 1: + return 0, c.err + default: + return 0, io.EOF + } +} + +func TestDecoderMore(t *testing.T) { + type Message struct{ Test int } + + notIgnoredError := errors.New("not ignored error") + dec := NewDecoder(&failingDecoderTestReader{t: t, err: notIgnoredError}) + + if val, err := dec.Token(); err != nil || val != Delim('[') { + t.Fatalf("(*Decoder).Token() = (%v, %v); want = ([, )", val, err) + } + + if err := dec.Decode(new(Message)); err != nil { + t.Fatalf("(*Decoder).Decode() = %v; want = ", err) + } + + if !dec.More() { + t.Fatalf("(*Decoder).More() = false; want = true") + } + + if err := dec.Decode(new(Message)); err != notIgnoredError { + t.Fatalf("(*Decoder).Decode() = %v; want = %v", err, notIgnoredError) + } + + if dec.More() { + t.Fatalf("(*Decoder).More() = true; want = false") + } + + if err := dec.Decode(new(Message)); err != io.EOF { + t.Fatalf("(*Decoder).Decode() = %v; want = %v", err, io.EOF) + } +}