Skip to content

Commit fca4b8e

Browse files
committed
contentjson: Add support for tailing comma
1 parent ae816ea commit fca4b8e

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

common/json/internal/contextjson/scanner.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ func stateEndValue(s *scanner, c byte) int {
300300
case parseObjectValue:
301301
if c == ',' {
302302
s.parseState[n-1] = parseObjectKey
303-
s.step = stateBeginString
303+
s.step = stateBeginStringOrEmpty
304304
return scanObjectValue
305305
}
306306
if c == '}' {
@@ -310,7 +310,7 @@ func stateEndValue(s *scanner, c byte) int {
310310
return s.error(c, "after object key:value pair")
311311
case parseArrayValue:
312312
if c == ',' {
313-
s.step = stateBeginValue
313+
s.step = stateBeginValueOrEmpty
314314
return scanArrayValue
315315
}
316316
if c == ']' {

common/json/internal/contextjson/stream.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ func (dec *Decoder) refill() error {
153153
dec.scanp = 0
154154
}
155155

156+
return dec.refill0()
157+
}
158+
159+
func (dec *Decoder) refill0() error {
156160
// Grow buffer if not large enough.
157161
const minRead = 512
158162
if cap(dec.buf)-len(dec.buf) < minRead {
@@ -402,15 +406,14 @@ func (dec *Decoder) Token() (Token, error) {
402406
return Delim('{'), nil
403407

404408
case '}':
405-
if dec.tokenState != tokenObjectStart && dec.tokenState != tokenObjectComma {
409+
if dec.tokenState != tokenObjectStart && dec.tokenState != tokenObjectComma && dec.tokenState != tokenObjectKey {
406410
return dec.tokenError(c)
407411
}
408412
dec.scanp++
409413
dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
410414
dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
411415
dec.tokenValueEnd()
412416
return Delim('}'), nil
413-
414417
case ':':
415418
if dec.tokenState != tokenObjectColon {
416419
return dec.tokenError(c)
@@ -483,7 +486,26 @@ func (dec *Decoder) tokenError(c byte) (Token, error) {
483486
// current array or object being parsed.
484487
func (dec *Decoder) More() bool {
485488
c, err := dec.peek()
486-
return err == nil && c != ']' && c != '}'
489+
// return err == nil && c != ']' && c != '}'
490+
if err != nil {
491+
return false
492+
}
493+
if c == ']' || c == '}' {
494+
return false
495+
}
496+
if c == ',' {
497+
scanp := dec.scanp
498+
dec.scanp++
499+
c, err = dec.peekNoRefill()
500+
dec.scanp = scanp
501+
if err != nil {
502+
return false
503+
}
504+
if c == ']' || c == '}' {
505+
return false
506+
}
507+
}
508+
return true
487509
}
488510

489511
func (dec *Decoder) peek() (byte, error) {
@@ -505,6 +527,25 @@ func (dec *Decoder) peek() (byte, error) {
505527
}
506528
}
507529

530+
func (dec *Decoder) peekNoRefill() (byte, error) {
531+
var err error
532+
for {
533+
for i := dec.scanp; i < len(dec.buf); i++ {
534+
c := dec.buf[i]
535+
if isSpace(c) {
536+
continue
537+
}
538+
dec.scanp = i
539+
return c, nil
540+
}
541+
// buffer has been scanned, now report any error
542+
if err != nil {
543+
return 0, err
544+
}
545+
err = dec.refill0()
546+
}
547+
}
548+
508549
// InputOffset returns the input stream byte offset of the current decoder position.
509550
// The offset gives the location of the end of the most recently returned token
510551
// and the beginning of the next token.

0 commit comments

Comments
 (0)