Actson: a reactive (or non-blocking, or asynchronous) JSON parser

Today I’m happy to an­nounce the very first ver­sion of Act­son, a re­act­ive JSON parser (some­times re­ferred to as non-block­ing or asyn­chron­ous). Act­son is event-based and can be used to­gether with re­act­ive lib­rar­ies/​tool-kits such as Rx­Java or Vert.x. The lib­rary is very small and has no de­pend­en­cies. It only re­quires Java 7 (or higher).

Down­load the Act­son bin­ar­ies from http://​search.maven.org or the source code from the Git­Hub re­pos­it­ory. Act­son is re­leased un­der the MIT li­cense.

Why another JSON parser?

  • Non-block­ing. Other JSON pars­ers use block­ing I/​O (i.e. they read from an InputStream). If you want to de­velop a re­act­ive ap­plic­a­tion you should use non-block­ing I/​O (see the Re­act­ive Mani­festo).
  • Big Data. Most pars­ers read the full JSON text into memory to map it to a POJO, for ex­ample. Act­son can handle ar­bit­rar­ily large JSON text. It is event-based and can be used for stream­ing.
  • GeoR­ocket. Act­son was primar­ily de­veloped for GeoR­ocket, a high-per­form­ance re­act­ive data store for geo­spa­tial files. We use Aalto XML to parse XML in a non-block­ing way and we needed something sim­ilar for GeoR­ock­et’s GeoJSON sup­port.

Usage

The JSON parser gets its in­put data from a feeder. Act­son uses a push-pull ap­proach: push data into the feeder un­til it is full. Then call the parser un­til it wants more data. Re­peat this pro­cess un­til the whole JSON text has been parsed.

The fol­low­ing snip­pet demon­strates how you can use the parser se­quen­tially.

// JSON text to parse
byte[] json = "{\"name\":\"Elvis\"}".getBytes(StandardCharsets.UTF_8);

JsonParser parser = new JsonParser(StandardCharsets.UTF_8);

int pos = 0; // position in the input JSON text
int event; // event returned by the parser
do {
    // feed the parser until it returns a new event
    while ((event = parser.nextEvent()) == JsonEvent.NEED_MORE_INPUT) {
        // provide the parser with more input
        pos += parser.getFeeder().feed(json, pos, json.length - pos);

        // indicate end of input to the parser
        if (pos == json.length) {
            parser.getFeeder().done();
        }
    }

    // handle event
    System.out.println("JSON event: " + event);
    if (event == JsonEvent.ERROR) {
        throw new IllegalStateException("Syntax error in JSON text");
    }
} while (event != JsonEvent.EOF);

Reactive, non-blocking examples

Find more com­plex and elab­or­ate us­age ex­amples in the Git­Hub re­pos­it­ory.

Similar libraries

  • Jack­son has a stream­ing API that pro­duces JSON tokens/​events. However, it uses block­ing I/​O be­cause it reads from an InputStream.
  • Aalto XML is sim­ilar to Act­son but parses XML in­stead of JSON.

Acknowledgments

The event-based parser code and the JSON files used for test­ing are largely based on the file JSON_checker.c and the JSON test suite from JSON.org ori­gin­ally re­leased un­der this li­cense (ba­sic­ally MIT li­cense).


Posted by Michel Krämer
on August, 19th 2016.