diff options
| author | Damien Neil <dneil@google.com> | 2025-12-08 13:09:05 -0800 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2025-12-11 09:34:26 -0800 |
| commit | 00642ee23b614d5314604b6b4d25c671f82c26b2 (patch) | |
| tree | 56e7f6b718760d455a62ce31192baaaac780e5db /src/encoding | |
| parent | 7b60d0673910a6527eb3d401b8a4e90c59cf70bd (diff) | |
| download | go-00642ee23b614d5314604b6b4d25c671f82c26b2.tar.xz | |
encoding/json: report true from v2 Decoder.More when an error is pending
Historically, Decoder.More reports true when the next read will
return an error. Adjust the v2 Decoder to follow this behavior.
Fixes #76467
Change-Id: I03bfa391e4e89ada8ca869db43c1d0bb63cc0413
Reviewed-on: https://go-review.googlesource.com/c/go/+/728300
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Joseph Tsai <joetsai@digital-static.net>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/encoding')
| -rw-r--r-- | src/encoding/json/stream_test.go | 12 | ||||
| -rw-r--r-- | src/encoding/json/v2_stream.go | 18 | ||||
| -rw-r--r-- | src/encoding/json/v2_stream_test.go | 12 |
3 files changed, 41 insertions, 1 deletions
diff --git a/src/encoding/json/stream_test.go b/src/encoding/json/stream_test.go index 0e937cfaa1..ba3bc4002b 100644 --- a/src/encoding/json/stream_test.go +++ b/src/encoding/json/stream_test.go @@ -459,6 +459,9 @@ func TestDecodeInStream(t *testing.T) { {CaseName: Name(""), json: ` \a`, expTokens: []any{ &SyntaxError{"invalid character '\\\\' looking for beginning of value", 1}, }}, + {CaseName: Name(""), json: `,`, expTokens: []any{ + &SyntaxError{"invalid character ',' looking for beginning of value", 0}, + }}, } for _, tt := range tests { t.Run(tt.Name, func(t *testing.T) { @@ -467,6 +470,15 @@ func TestDecodeInStream(t *testing.T) { var got any var err error + wantMore := true + switch want { + case Delim(']'), Delim('}'): + wantMore = false + } + if got := dec.More(); got != wantMore { + t.Fatalf("%s:\n\tinput: %s\n\tdec.More() = %v, want %v (next token: %T(%v))", tt.Where, tt.json, got, wantMore, want, want) + } + if dt, ok := want.(decodeThis); ok { want = dt.v err = dec.Decode(&got) diff --git a/src/encoding/json/v2_stream.go b/src/encoding/json/v2_stream.go index dcee553ee1..ca0822cb73 100644 --- a/src/encoding/json/v2_stream.go +++ b/src/encoding/json/v2_stream.go @@ -197,6 +197,9 @@ 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 { + return nil, dec.err + } tok, err := dec.dec.ReadToken() if err != nil { // Historically, v1 would report just [io.EOF] if @@ -238,7 +241,20 @@ func (dec *Decoder) Token() (Token, error) { func (dec *Decoder) More() bool { dec.hadPeeked = true k := dec.dec.PeekKind() - return k > 0 && k != ']' && k != '}' + if k == 0 { + if dec.err == nil { + // PeekKind doesn't distinguish between EOF and error, + // so read the next token to see which we get. + _, err := dec.dec.ReadToken() + if err == nil { + // This is only possible if jsontext violates its documentation. + err = errors.New("json: successful read after failed peek") + } + dec.err = transformSyntacticError(err) + } + return dec.err != io.EOF + } + return k != ']' && k != '}' } // InputOffset returns the input stream byte offset of the current decoder position. diff --git a/src/encoding/json/v2_stream_test.go b/src/encoding/json/v2_stream_test.go index 0885631fb5..d7f9f11084 100644 --- a/src/encoding/json/v2_stream_test.go +++ b/src/encoding/json/v2_stream_test.go @@ -439,6 +439,9 @@ func TestDecodeInStream(t *testing.T) { {CaseName: Name(""), json: ` \a`, expTokens: []any{ &SyntaxError{"invalid character '\\\\' looking for beginning of value", len64(` `)}, }}, + {CaseName: Name(""), json: `,`, expTokens: []any{ + &SyntaxError{"invalid character ',' looking for beginning of value", 0}, + }}, } for _, tt := range tests { t.Run(tt.Name, func(t *testing.T) { @@ -447,6 +450,15 @@ func TestDecodeInStream(t *testing.T) { var got any var err error + wantMore := true + switch want { + case Delim(']'), Delim('}'): + wantMore = false + } + if got := dec.More(); got != wantMore { + t.Fatalf("%s:\n\tinput: %s\n\tdec.More() = %v, want %v (next token: %T(%v)) rem:%q", tt.Where, tt.json, got, wantMore, want, want, tt.json[dec.InputOffset():]) + } + if dt, ok := want.(decodeThis); ok { want = dt.v err = dec.Decode(&got) |
