Description
JsonObjectParser rejects valid JSON input when the top-level structure is not a JSON object. The 256-byte lookup table (outerChars) only tolerates {, [, ], ,, and whitespace at depth 0 outside a string. Any other byte causes a FramingException with the misleading message "Invalid JSON encountered".
Affected code
stream/src/main/scala/org/apache/pekko/stream/impl/JsonObjectParser.scala (lines 170-180):
private val outerChars: Array[Byte] =
Array.tabulate[Byte](256) { i =>
i.toByte match {
case CurlyBraceStart => 2 // found object
case SquareBraceStart | SquareBraceEnd | Comma => 1 // skip
case b if isWhitespace(b.toByte) => 1 // skip
case _ => 0 // error
}
}
At depth 0, encountering a byte with value 0 triggers 1 / outer (line 142), raising ArithmeticException, which is converted to a FramingException.
Valid JSON inputs that are incorrectly rejected
| Input |
Why rejected |
42 (bare number) |
4 → outer=0 |
"hello" (bare string) |
" → outer=0 |
true / null / false |
t/n/f → outer=0 |
[[1], [2]] (array of arrays) |
digits not in skip set |
\xEF\xBB\xBF{"a":1} (UTF-8 BOM) |
0xEF → outer=0 |
Documentation inconsistency
JsonFraming.scala line 56 states "a top-level JSON Array can also be understood" — but this only works for arrays of objects, not arrays of primitives or arrays of arrays.
Suggested improvements
- Make the error message more specific: distinguish between "Invalid JSON" and "Top-level JSON element is not a JSON object"
- Clarify the documentation to state that
JsonFraming.objectScanner only frames JSON objects
- Consider supporting UTF-8 BOM at the start of input (strip
\xEF\xBB\xBF before parsing)
Description
JsonObjectParserrejects valid JSON input when the top-level structure is not a JSON object. The 256-byte lookup table (outerChars) only tolerates{,[,],,, and whitespace at depth 0 outside a string. Any other byte causes aFramingExceptionwith the misleading message "Invalid JSON encountered".Affected code
stream/src/main/scala/org/apache/pekko/stream/impl/JsonObjectParser.scala(lines 170-180):At depth 0, encountering a byte with value
0triggers1 / outer(line 142), raisingArithmeticException, which is converted to aFramingException.Valid JSON inputs that are incorrectly rejected
42(bare number)4→ outer=0"hello"(bare string)"→ outer=0true/null/falset/n/f→ outer=0[[1], [2]](array of arrays)\xEF\xBB\xBF{"a":1}(UTF-8 BOM)Documentation inconsistency
JsonFraming.scalaline 56 states "a top-level JSON Array can also be understood" — but this only works for arrays of objects, not arrays of primitives or arrays of arrays.Suggested improvements
JsonFraming.objectScanneronly frames JSON objects\xEF\xBB\xBFbefore parsing)