Replacing JSON when talking to Erlang

Datetime:2016-08-23 04:41:46          Topic: Erlang           Share

What I like about JSON in the first place

JSON is awesome, supported pretty much everywhere, easy to read without any extra tools (I'm looking at you BSON and Protocol Buffers) and way better than XML.

However, parsing JSON costs cycles and they are still verbose and larger than their BSON and Protobuf counterparts. What this means in practice, is that if we are paying for hosting, we are paying extra to encode/decode the JSONs and the extra bandwidth we are going to use.

However, we already have a nice JSON alternative in Erlang, External Term Format , the way erlang communicates between nodes and that can, obviously, be processed really fast on the erlang side. As a nice bonus, though not as small as protobuff, it's still pretty compact (specially when compared to JSON, and god forbid, XML), so we can save some valuable bandwidth.

So, how hard would it be to communicate with Erlang in a way it can easily understand? Not at all really; the ETF is quite simple to understand, specially if we consider that we only need to support a subset of all its idioms.

Replacing JSONs with Jem.js

But still, writing it from scratch takes some work; so instead of just suggesting you should write it, use ours! Jem.js will support any JSON object jiffy would.

Just call Inaka.Jem.encode(someObject) from you JS code and get a nice array of bytes to send to Erlang, or call Inaka.Jem.decode(someBytes) to get a nice object. The Erlang counterparts to this two are obviously just term_to_binary/1 and binary_to_term/1 so it will be really easy to implement; just remember you are not sending application/json , but application/erlang , so set your content-types accordingly.

How does this look on the Erlang side? Let's look at an example I'm sure we all came across a few times:

handle_post(Req, State) ->
  {ok, Body, Req1} = cowboy_req:body(Req),
  Decoded = jiffy:decode(Body, [return_maps]),
  Reply = do_whatever(Decoded),
  {jiffy:encode(Reply), Req1, State}.

What should we do if we get all the requests in ETF? Just replace the jiffy calls!

handle_post(Req, State) ->
  {ok, Body, Req1} = cowboy_req:body(Req),
  Decoded = erlang:binary_to_term(Body),
  Reply = do_whatever(Decoded),
  {erlang:term_to_binary(Reply), Req1, State}.

Faster and more efficient, but why do we need to use it? Well, if you are the one footing the hosting bill, then what reason do you have not to? You'll definitely save both bandwidth and cycles with minimal effort on your part.





About List