See: http://jsonapi.org
scala-streamable-jsonapi consists of three major components:
- Parser (JsonApiParser)
- Generator (JsonApiGenerator)
- Handler
Parser works with Jackson generic parser (which deals with streaming internally),
to return a stream of jsonapi compliant jsons for streamed members (data
, included
, errors
),
or as a simple json objects for (meta
, jsonapi
, links
). data
member can be streamed or not depending
if it's an Array of objects or not.
Generator provides a interface to write jsons to Jackson streamed writer.
Handler works together with parser. It receives data extracted by parser, it'a an interface for client to be able to react on events.
Initialization:
new JsonApiParser(instance of java.io.InputStream, handlerObject)
During parsing input stream parser will call methods on instance on handler. See handler section below for more.
Initialization:
new JsonapiGenerator(instance of java.io.OutputStream)
Client software should call appropriate methods on instance of generator and pass data to be written to it.
Handler is a interface for parser, it implements following methods:
def endDocument: Any = {}
def startData: Any = {}
def endData: Any = {}
def data(obj: Map[String, Any]): Any = {}
def startIncluded: Any = {}
def endIncluded: Any = {}
def resource(obj: Map[String, Any]): Any = {}
def startErrors: Any = {}
def endErrors: Any = {}
def error(obj: Map[String, Any]): Any = {}
def meta(obj: Map[String, Any]): Any = {}
def jsonapi(obj: Map[String, Any]): Any = {}
def links(obj: Map[String, Any]): Any = {}
Names correspond to jsonapi members so it's pretty straightforward to understand which one is called when.
Note: during streamed parsing of data
or included
extracted jsons as Map[String, Any]
are passed to handler via the resource
method.
data
method is only used IF data
section in parsed json is a single json object.
###Examples
When doing streamed parsing and serving response also as a stream using a JsonApiGenerator do not forget to call
close()
explicitly. Otherwise for client request will never be considered as finished.
def createStructureFromStream(): Unit = {
txWithCheckpoint(checkPoint => new Parser(new StructureCreator(phase, uploadInfo, filename, checkPoint)).readStream,
failIf = () => uploadInfo.anyErrors)
uploadInfo.close()
}