diff options
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) |
