Skip to content
This repository has been archived by the owner on Jan 12, 2023. It is now read-only.

5. Pre encode and post decode

Richard Jonas edited this page May 17, 2016 · 4 revisions

Converting data during encoding and decoding

We have the most powerful tool which we need to use wisely. For almost each type of data we can pre-process values before encoding and also we can post-process values after decoding data from JSON. Let us a simple example for that. Suppose that we need to convert os:timestamp() to ISO date format.

%% We serialize log messages where both the message
%% and the time will be binary (string) in JSON.
-json({log, {binary, message},
            {binary, time, [{pre_encode, {?MODULE, time_to_binary}},
                            {post_decode, {?MODULE, binary_to_time}}]
            }
      }).

-export([time_to_binary/2, binary_to_time/2]).

time_to_binary(_LogRecord, Time) ->
    %% We got the whole record and the time before encoding
    %% Time is supposed to be a os:timestamp() result
    %% We convert something like 2011-08-28T15:41:09Z
    {{Y, Mo, D}, {H, Mi, S}} = calendar:now_to_local_time(Time),
    io_lib:format("~4..0B-~2..0B-~2..0BT~2..0B:~2..0B:~2..0BZ",
                    [Y, Mo, D, H, Mi, S])).

binary_to_time(_Record, IsoDate) ->
    %% Here we have a structure which is half-ready in the first
    %% parameter. It is in jsx raw format like:
    %% [{<<"attr1">>, <<"value1">>}, ...] where value part can be
    %% a binary, a boolean, a number or undefined
    parse_iso_to_date(IsoDate).

parse_iso_date(<<Y1, Y2, Y3, Y4, $-, Mo1, Mo2, $-, D1, D2, $T,
                 H1, H2, $:, Mi1, Mi2, $:, S1, S2, $.,
                 Ms1, Ms2, Ms3, $Z>>) ->
    try {{list_to_integer([Y1, Y2, Y3, Y4]),
          list_to_integer([Mo1, Mo2]),
          list_to_integer([D1, D2])},
         {list_to_integer([H1, H2]),
          list_to_integer([Mi1, Mi2]),
          list_to_integer([S1, S2]),
          list_to_integer([Ms1, Ms2, Ms3])}} of
        Date -> {ok, Date}
    catch
        error:badarg ->
            {error, date_format_error}
    end;
parse_iso_date(_) ->
    {error, date_format_error}.
Clone this wiki locally