/ejsonpath

JSONPath Erlang implementation

Primary LanguageErlangApache License 2.0Apache-2.0

eJSONPath - jsonpath for erlang

eJSONPath is pure-erlang implementation of JSONPath. It uses jiffy JSON structure ({[ {key(), value()}, ...]} for structs) and implements most of the JSONPath description (I don't say specification, because there is no such thing like jsonpath spec).

  • Robust extensible parser (leex + yecc).
  • Extensible by custom functions.
  • No dependencies (but you may want jiffy as json parser).

Examples

{ok, Bin} = file:read_file("test/doc.json").
Doc = jiffy:decode(Bin).

%% return 1'st book author
[<<"Nigel Rees">>] = ejsonpath:execute("$.store.book[0].author", Doc).

%% return 1'st book categody and author
[<<"reference">>,
 <<"Nigel Rees">>] = ejsonpath:execute("$.store.book[0]['category','author']", Doc).

%% return only reference book authors
%% `Funs' is a list of `{Name, Fun}' pairs (see Fun spec on sources)
Funs = [
{<<"filter_category">>,
 fun({{Pairs}, _Doc}, [CategoryName]) ->
     case proplists:get_value(<<"category">>, Pairs) of
         CategoryName -> true;
         _ -> false
     end
 end}
],
[<<"Nigel Rees">>] = ejsonpath:execute(
                     "$.store.book[?(filter_category('reference'))].author", Doc, Funs).

More examples in tests.

JSONPath coverage

Since there is no such thing as JSONPath specification, every implementer create it's own variations. But I try to follow description from JSONPath as close as possible.

+-----------------------+---------------------+-----------+
| Feature               | Example             |Implemented|
+-----------------------+---------------------+-----------+
|Dot filtering          |`$.one.two`          | Y         |
+-----------------------+---------------------+-----------+
|Brace filtering        |`$['one']['two']`    | Y         |
+-----------------------+---------------------+-----------+
|Array slicing          | `$[1,2,3]` `$.o[2]` | Y         |
+-----------------------+---------------------+-----------+
|Hash slicing           | `$['one', 'two']`   | Y         |
+-----------------------+---------------------+-----------+
|Asterisk (hash, array) | `$.one.*` `$.one[*]`| Y         |
+-----------------------+---------------------+-----------+
|Python-slicing         | `$[1:-1:2]`         | Partial*  |
+-----------------------+---------------------+-----------+
|Eval binary filter     | `$[?(true)]`        | Partial** |
+-----------------------+---------------------+-----------+
|Eval index             | `$[('one')]`        | Partial** |
+-----------------------+---------------------+-----------+
|Recursive descent      | `..`                | N         |
+-----------------------+---------------------+-----------+

* Only step=1 supported now
** Very limited scripting language: string, integer and function calls

Most of the missing features can be implemented as custom functions

$.one[?( custom_function_call('arg1', 42) )]
$.two[( custom_function_call() )]

TODO

  • Implement missing features
  • Python slicing step support. (Currently only step==1 supported)
  • Recursive descent (supported by parser, need evaluator)
  • Eval filter / index - allow path expressions and operators $[?(@.category)]
  • Eval filter / index - allow binary operators $[?(@.category!='reference')]
  • Support for alternative JSON representations (mochijson2, EEP-18)

Other implementations

License

Apache v2