A minimalistic JSON parser for scala. Its goals:
The parser is hand-crafted, resulting in very good performance. It's up to par with Jackson, more than 350 times faster than the default json parser (that shipped with scala until 2.10), and more than 15 times faster than the spray-json parser. (Running the tests will report timing information.)
The parser streams its result into a json handler. The handler gets events from the parser and can act accordingly. It allows for memory-efficient processing of large data sets.
The core parser is not tied to a particular JSON AST (abstract syntax tree). Through the streaming interface, any AST can be built. The parser currently ships with a spray-json builder, more will follow.
The json-parser can be obtained from maven central, cross-built against scala 2.10 and 2.11:
"org.scalastuff" %% "json-parser" % "2.0.2"
import org.scalastuff.json.JsonParser val parser = new JsonParser(new MyJsonHandler)
The parser has three parse overloads:
def parse(reader: Reader) def parse(source: String) def parse(source: Array[Char])
Reader overload allows streaming some JSON input into the parser. The document will be processed character-by-character, the input will not be read into memory.
Array[Char] overloads are wrappers around the
Reader overload, but they use an optimized reader, FastStringReader. Compared to using
java.io.CharArrayReader, expect a speedup of nearly 50%.
Note that a parser instance is NOT thread safe. It can be re-used though, and one is advised to do so.
The parser ships with a built-in spray parser, targeting the spray-json AST:
import spray.json.JsValue import org.scalastuff.json.spray.SprayJsonParser val parser = new SprayJsonParser val result: JsValue = parser.parse(someJson)
It also has an 'object' interface, that adds some convenience. It creates a parser instance on each invocation, which can be useful in a multi-threaded environment:
val result: JsValue = SprayJsonParser.parse(someJson)
Note: to use this parser in the context of spray.io (e.g. in spray-routing), one should use an alternative implementation of
spray.httpx.SprayJsonSupport. Providing such an implementation is out of scope for this project though.
Writing a JsonHandler
A JsonHandler is a call-back interface for parse events, comparable to SAX for XML.
Reader in combination with a custom handler allows for true streamed JSON processing.
The SprayJsonBuilder is probably a good starting point when writing a custom handler.
The JsonPrinter pretty-prints json to a given writer. It is a handler, so it can be fed to the parser. The following example illustrates how file data can can be pretty-printed and directly streamed to an output stream:
val reader = new FileReader("data.json") val writer = new OutputStreamWriter(System.out) val parser = new JsonParser(new JsonPrinter(writer)) parser.parse(reader) writer.close()
- Allow for asynchronous, 'reactive' streaming. See issue #3.
This software is released under the Apache License, Version 2.0