-
Notifications
You must be signed in to change notification settings - Fork 16
1. Welcome to ejson
ejson
is a JSON encoding/decoding library for Erlang. It gives a declarative interface for jsx
by which we need to specify conversion rules and ejson
will convert tuples according to the rules.
Using ejson one should define rules which gives a mapping for each field of a record describing how to convert the field possible values to JSON. ejson is intended to create such a conversion system with which one can easily decode JSONs back to Erlang records. So at first the rules can seem to be complicated but there reason is that we can convert and parse (encode and decode) terms and JSONs.
-module(people).
%% You can specify in rebar.config, erlang.mk, too.
-compile({parse_transform, ejson_trans}).
%% Record definitions are not needed for ejson but you.
-record(person, {name, birth_year, projects}).
-record(project, {name, budget, successful}).
-json({person, {string, "name"}, {number, "yearOfBirth"},
{list, "projects", [{type, project}]}]}).
-json({project, {string, "name"}, {number, "budget"},
{boolean, "isSuccessful"}]}).
%% parse_transform generates to_json/1 and from_json/{1,2} local functions
start() ->
Jim = #person{
name = "Jim",
birth_year = 1967,
projects = [#project{name = "Authoring",
budget = 100000
successful = true}]},
{ok, Json} = to_json(Jim),
io:format("~s~n", [Json]),
{ok, Person} = from_json(Json, person). %% Specify the the expected type here
The person record results in a JSON like this:
{
"name": "Jim",
"yearOfBirth": 1967,
"projects": [
{
"name": "Authoring",
"budget": 100000,
"isSuccessful": true
}
]
}
ejson
(by the help of ejson_trans
parse transform) reads compiled modules which are compiled with that parse transform. It collects all -json(...)
wild attributes to get the conversion rules for different record types. It also defines 3 functions in the module to be compiled (if they are not defined already).
to_json(Record) -> {ok, JSON::binary()} | {error, Reason::term()}.
from_json(Json) -> {ok, Record::term()} | {error, Reason::term()}.
from_json(Json, ExpectedType::atom()) -> {ok, Record::term()} | {error, Reason::term()}.
Those functions are for converting records to JSON and parsing JSON to records. Those functions are not exported since they are intended to be used in the current module as private function. To avoid compiler warnings the parse transform puts nowarn_unused_function
compile attributes into the module in order that compiler doesn't complain for those "invisible" functions when they are not used.
to_json/1
converts records to json binaries, from_json/2
parse json binary and apply the rules to extract the record specified in the second parameter. In ejson
we can convert records in a way that the JSON will contain a meta-type field (__rec
field) which stores from what record the JSON has been converted. So in that way we can use from_json/1
to decode records back. The only disadvantage of that method is that JSONs will contain a __rec
field, so picky applications may not accept those JSONs (or remove that field when sending JSONs back).