Euneus
What is Euneus?
A JSON parser and generator in pure Erlang. Euneus is a rewrite of Thoas. Like Thoas, both the parser and generator fully conform to RFC 8259 and ECMA 404.
Why Euneus over Thoas?
Thoas is incredible, works performant and perfectly fine, but Euneus is more flexible, permitting more customizations. The motivation for Euneus is this PR when I was looking for options to not traverse lists and maps to customize terms.
How does it perform?
Note
Encode
##### With input Blockchain #####
Name ips average deviation median 99th %
euneus 10.56 K 94.69 μs ±15.18% 95.53 μs 139.58 μs
Jason 10.35 K 96.58 μs ±16.88% 85.48 μs 155.88 μs
thoas 7.42 K 134.68 μs ±9.91% 135.49 μs 175.04 μs
Comparison:
euneus 10.56 K
Jason 10.35 K - 1.02x slower +1.89 μs
thoas 7.42 K - 1.42x slower +39.99 μs
Memory usage statistics:
Name Memory usage
euneus 83.10 KB
Jason 78.91 KB - 0.95x memory usage -4.19531 KB
thoas 89.41 KB - 1.08x memory usage +6.31 KB
Decode
##### With input Blockchain #####
Name ips average deviation median 99th %
euneus 6.98 K 143.35 μs ±5.22% 141.99 μs 178.33 μs
Jason 6.93 K 144.26 μs ±14.21% 140.26 μs 274.38 μs
thoas 5.65 K 177.01 μs ±8.87% 175.34 μs 252.45 μs
Comparison:
euneus 6.98 K
Jason 6.93 K - 1.01x slower +0.91 μs
thoas 5.65 K - 1.23x slower +33.66 μs
Memory usage statistics:
Name Memory usage
euneus 51.41 KB
Jason 51.63 KB - 1.00x memory usage +0.21 KB
thoas 51.41 KB - 1.00x memory usage +0 KB
Installation
Euneus is available at Hex.
Erlang
% rebar.config
{deps, [{euneus, "0.7.0"}]}
Elixir
def deps do
[{:euneus, "~> 0.7"}]
end
Customizations
Please see the README file in the repository for more info.
Encode
#{
%% nulls defines what terms will be replaced with the null literal (default: ['undefined']).
nulls => nonempty_list(),
%% binary_encoder allow override the binary() encoding.
binary_encoder => function((binary(), euneus_encoder:options()) -> iolist()),
%% atom_encoder allow override the atom() encoding.
atom_encoder => function((atom(), euneus_encoder:options()) -> iolist()),
%% integer_encoder allow override the integer() encoding.
integer_encoder => function((integer(), euneus_encoder:options()) -> iolist()),
%% float_encoder allow override the float() encoding.
float_encoder => function((float(), euneus_encoder:options()) -> iolist()),
%% list_encoder allow override the list() encoding.
list_encoder => function((list(), euneus_encoder:options()) -> iolist()),
%% map_encoder allow override the map() encoding.
map_encoder => function((map(), euneus_encoder:options()) -> iolist()),
%% datetime_encoder allow override the calendar:datetime() encoding.
datetime_encoder => function((calendar:datetime(), euneus_encoder:options()) -> iolist()),
%% timestamp_encoder allow override the erlang:timestamp() encoding.
timestamp_encoder => function((erlang:timestamp(), euneus_encoder:options()) -> iolist()),
%% unhandled_encoder allow encode any custom term (default: raise unsupported_type error).
unhandled_encoder => function((term(), euneus_encoder:options()) -> iolist()),
%% escaper allow override the binary escaping (default: json)
escaper => json
| html
| javascript
| unicode
| function((binary(), euneus_encoder:options()) -> iolist()),
error_handler => function(( error | exit | throw
, term()
, erlang:stacktrace() ) -> euneus_encoder:result())
}
Decode
#{
%% null_term is the null literal override (default: 'undefined').
null_term => term(),
%% arrays allow override any array/list().
arrays => function((list(), euneus_decoder:options()) -> term()),
%% objects allow override any object/map().
objects => function((map(), euneus_decoder:options()) -> term()),
%% keys allow override the keys from JSON objects.
keys => copy
| to_atom
| to_existing_atom
| to_integer
| function((binary(), euneus_decoder:options()) -> term()),
%% values allow override any other term, like array item or object value.
values => copy
| to_atom
| to_existing_atom
| to_integer
| function((binary(), euneus_decoder:options()) -> term())
}
Decode resuming
Euneus permits resuming the decoding when an invalid token is found. Any value can replace the invalid token by overriding the error_handler
option. Please see an example here.
Credits
Euneus is a rewrite of Thoas, so all credits go to Michał Muskała, Louis Pilfold, also both Jason and Thoas contributors. Thanks for the hard work!