Skip to content

Commit 9d4e68d

Browse files
committed
encoding/json: reduce the number of allocations when decoding in streaming mode (Token API)
When the scanner is used by the Token API it always resets the state before so that the scanner behaves as if it was parsing a top-level value, which causes it to allocate and set the 'err' field because the following character is not a space. This error value is completely unnecessary because it's dropped by the next invocation of readValue(). Fixes #56299
1 parent 4fb35d6 commit 9d4e68d

File tree

2 files changed

+17
-0
lines changed

2 files changed

+17
-0
lines changed

src/encoding/json/scanner.go

+12
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ type scanner struct {
7373
// Reached end of top-level value.
7474
endTop bool
7575

76+
// The scanner is used in streaming mode (i.e. by the Token API)
77+
inStream bool
78+
7679
// Stack of what we're in the middle of - array values, object keys, object values.
7780
parseState []int
7881

@@ -280,6 +283,15 @@ func stateEndValue(s *scanner, c byte) int {
280283
n := len(s.parseState)
281284
if n == 0 {
282285
// Completed top-level before the current byte.
286+
if s.inStream {
287+
// If used in streaming mode (i.e. by the Token API) do not allocate and set s.err in case the next
288+
// character is non-space (which stateEndTop() would do). The error would be discarded anyway at the next
289+
// call to readValue().
290+
if s.err != nil {
291+
return scanError
292+
}
293+
return scanEnd
294+
}
283295
s.step = stateEndTop
284296
s.endTop = true
285297
return stateEndTop(s, c)

src/encoding/json/stream.go

+5
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,11 @@ func (d Delim) String() string {
369369
// to mark the start and end of arrays and objects.
370370
// Commas and colons are elided.
371371
func (dec *Decoder) Token() (Token, error) {
372+
dec.scan.inStream = true
373+
defer func() {
374+
dec.scan.inStream = false
375+
}()
376+
372377
for {
373378
c, err := dec.peek()
374379
if err != nil {

0 commit comments

Comments
 (0)