Parse JSON as a stream.
This parser reads the JSON into memory only as it is parsed.
This makes it more complicated than the watt.json.dom parser,
but more flexible.
Code Map
//! Parse JSON as a stream.
module watt.json.sax;
//! Type of a JSON value.
enum Type
{
//! A JSON null value.
NULL,
//! A JSON true or false value.
BOOLEAN,
//! A JSON number.
NUMBER,
//! A JSON string.
STRING,
//! A JSON object, everything between {}.
OBJECT,
//! A JSON array, everything between [].
ARRAY,
}
//! Events which will be produced by get.
enum Event
{
//! The first event, marks the start of the JSON data.
START,
//! The last event, marks the end of the JSON data.
END,
//! Event which will occour if invalid JSON is encountered.
ERROR,
//! A null was encountered.
NULL,
//! A boolean was encountered.
BOOLEAN,
//! A number was encountered.
NUMBER,
//! A string was encountered.
STRING,
//! The start of a JSON object was encountered.
OBJECT_START,
//! A JSON object key was encountered (this is a string and still needs to
//! be unescaped).
OBJECT_KEY,
//! The end of a JSON object was encountered.
OBJECT_END,
//! The start of a JSON array was encountered.
ARRAY_START,
//! The end of a JSON array was encountered.
ARRAY_END,
}
//! Thrown when an error occurs during building.
class BuilderException : util.JSONException
{
public:
this(msg: string, location: string) { }
}
//! Parses JSON from a given InputStream.
class SAX
{
public:
//! Ignore garbage/left over data after the root element is parsed.
ignoreGarbage: bool;
public:
//! Creates a JSON object from an InputStream.
this(source: InputStream, bufferSize: size_t, reallocSize: size_t) { }
//! Creates a JSON object from an array.
this(data: const(u8)[]) { }
//! Creates a JSON object from a string.
this(data: const(char)[]) { }
//! Continues parsing the input data and calsl the callback with the
//! appropriate data.
fn get(callback: scope (void delegate(Event, const(u8)[]))) { }
protected:
source: InputStream;
buffer: u8[];
reallocSize: size_t;
current: const(u8)[];
index: size_t;
savedMark: size_t;
isMarked: bool;
state: ParserStack;
lastError: string;
protected:
fn error(message: string, file: string, line: const(i32)) { }
fn eof() bool { }
fn mark() { }
fn retrieve() const(u8)[] { }
fn getImpl(c: char, skip: bool, advance: bool) bool { }
fn unget() { }
fn skipWhite() { }
fn skipDigits() bool { }
fn expect(c: char, skip: bool) bool { }
fn getString(array: const(u8)[]) bool { }
fn getNumber(array: const(u8)[]) bool { }
fn getBoolean(array: const(u8)[]) bool { }
fn getNull(array: const(u8)[]) bool { }
}
//! The main class to build/write JSON.
class Builder
{
public:
//! Creates a new JSONBuilder object.
this(output: OutputStream, prettyPrint: bool, indent: const(char)[]) { }
//! Writes a null value.
fn buildNull() { }
//! Writes a number.
fn buildNumber(number: f64) { }
//! Writes a number.
fn buildNumber(number: i32) { }
//! Writes a number.
fn buildNumber(number: i64) { }
//! Writes a string.
fn buildString(str: const(char)[], escape: bool) { }
//! Writes a boolean.
fn buildBoolean(b: bool) { }
//! Writes the start of a JSON object.
fn buildObjectStart() { }
//! Writes the end of a JSON object.
fn buildObjectEnd() { }
//! Writes the start of a JSON array.
fn buildArrayStart() { }
//! Writes the end of a JSON array.
fn buildArrayEnd() { }
//! Finalizes the JSON.
fn finalize() { }
protected:
output: OutputStream;
prettyPrint: bool;
indent: const(char)[];
indentLevel: size_t;
buffer: char[];
state: ParserStack;
protected:
fn prepareAndCheck(isString: bool) { }
}
//! Turn an Event into a human readable string.
fn eventToString(event: Event) string { }
Thrown when an error occurs during building.
Type of a JSON value.
A JSON null
value.
A JSON true
or false
value.
A JSON number.
A JSON string.
A JSON object, everything between {}.
A JSON array, everything between [].
Events which will be produced by get.
The first event, marks the start of the JSON data.
The last event, marks the end of the JSON data.
Event which will occour if invalid JSON is encountered.
A null was encountered.
A boolean was encountered.
A number was encountered.
A string was encountered.
The start of a JSON object was encountered.
A JSON object key was encountered (this is a string and still needs to be unescaped).
The end of a JSON object was encountered.
The start of a JSON array was encountered.
The end of a JSON array was encountered.
Turn an Event
into a human readable string.
Parses JSON from a given InputStream.
Ignore garbage/left over data after the root element is parsed.
Creates a JSON object from an InputStream
.
Creates a JSON object from an array.
Creates a JSON object from a string.
Continues parsing the input data and calsl the callback with the appropriate data.
This is the main entrypoint into the SAX parser. The basic idea
is that callback
will be called with 'events' (triggered by pieces
of JSON).
Here's a simple example that parses an entire file from standard input, and does nothing with it.
sax := new Sax(input); // input is declared in watt.io.std.
loop := true;
fn dgt(event: Event, data: const(u8)[]) {
loop = event == Event.END || event == Event.ERROR;
}
while (loop) sax.get(dgt);
data
is a slice to an internal buffer and will only be valid
until the next get
call. Strings and numbers still need to be
further processed. e.g. through parseDouble and
unescapeString.
The main class to build/write JSON.
This is the opposite of SAX
. Instead of taking input and processing it,
this writes out JSON to a given OutputStream.
Creates a new JSONBuilder
object.
Parameters
output |
The |
prettyPrint |
If true emit formatted JSON |
indent |
: Only relevant if |
Writes a null value.
Writes a number.
Writes a number.
Writes a number.
Writes a string.
If escape
is true
(default) the string will
be escaped, set this to false
if you want to write an
already escaped strings.
Writes a boolean.
Writes the start of a JSON object.
JSON keys are expected to be built with buildString
.
Writes the end of a JSON object.
Writes the start of a JSON array.
Writes the end of a JSON array.
Finalizes the JSON.
This is optional but recommended,
it checks for malformed JSON and writes an additional newline
if prettyPrint
is enabled.