factor out gen_json

This commit is contained in:
alisdair sullivan 2012-03-02 22:53:23 -08:00
parent 61ef73ff72
commit 63faf04115
8 changed files with 20 additions and 184 deletions

View file

@ -6,12 +6,12 @@ copyright 2011, 2012 alisdair sullivan
jsx is released under the terms of the [MIT][MIT] license
## quickstart ##
to build jsx, `make` or `./rebar compile`
## api ##
**converting json to erlang terms**
parses a JSON text (a utf8 encoded binary) and produces an erlang term (see json <-> erlang mapping details below)
@ -173,77 +173,6 @@ json arrays are represented with erlang lists of json values as described in thi
json objects are represented by erlang proplists. the empty object has the special representation `[{}]` to differentiate it from the empty list. ambiguities like `[true, false]` prevent using the shorthand form of property lists using atoms as properties. all properties must be tuples. all keys must be encoded as in `string`, above, or as atoms (which will be escaped and converted to binaries for presentation to handlers)
## gen_json ##
jsx is implemented as a set of scanners that produce tokens consumed be functions that transform them into various representations. `gen_json` is an interface to allow arbitrary representations/actions to be taken upon scanning a json text or erlang term representation of a json text
**the gen_json parser**
`gen_json:parser(Mod)` -> `Result`
`gen_json:parser(Mod, Args)` -> `Result`
`gen_json:parser(Mod, Args, Opts)` -> `Result`
types:
* `Mod` = module()
* `Args` = any()
* `Opts` = see note below
`Mod` is the callback module implementing the `gen_json` behaviour
`Args` will be passed to `Mod:init/1` as is
`Result` will be the return from `Mod:handle_event(end_json, State)`
in general, `Opts` will be passed as is to the scanner. the scanner will be automatically selected based on input type. to specify a specific scanner, you may use the options `{parser, Parser}` where `Parser` can currently be one of `auto`, `encoder` or `decoder`. `auto` is the default behaviour, `encoder` will only accept erlang terms (as in the mapping detailed above) and `decoder` will only accept json texts. note that to parse naked erlang terms as json, you MUST specify `{parser, encoder}`. more scanners may be added in the future
modules that implement the `gen_json` behaviour must implement the following two functions
**init**
produces the initial state for a gen_json handler
`init(Args)` -> `InitialState`
types:
* `Args` = `any()`
* `InitialState` = `any()`
`Args` is the argument passed to `gen_json/2` above as `Args`. when `gen_json/1` is called, `Args` will equal `[]`
**handle_event**
`handle_event/2` will be called for each token along with the current state of the handler and should produce a new state
`handle_event(Event, State)` -> `NewState`
types:
* `Event` =
- `start_object`
- `end_object`
- `start_array`
- `end_array`
- `end_json`
- `{key, list()}`
- `{string, list()}`
- `{integer, integer()}`
- `{float, float()}`
- `{literal, true}`
- `{literal, false}`
- `{literal, null}`
* `State` = `any()`
`Event` types are detailed in the mapping section, above. any cleanup in your handler should be done upon receiving `end_json` as it will always be the last token received
## acknowledgements ##
paul davis, lloyd hilaiel, john engelhart, bob ippolito, fernando benavides and alex kropivny have all contributed to the development of jsx, whether they know it or not