timestamper/src/ts_json.erl
Jonathan Bernard 9b3f587974 Changed record keys to use lists instead of atoms.
Using atoms will not scale in the large. Also, using atoms as keys forced the
API to convert arbitrary end-user input to atoms, adding another potential
drain of the finite atom-space available.

- ts_api: url paths are now treated and matched as lists, not atoms.
  Usernames and API calls all use lists now.
- ts_json: key items (username, timeline ids) are now expected to be lists,
  not atoms.
2011-05-03 12:24:23 -05:00

87 lines
3.0 KiB
Erlang

-module(ts_json).
-export([encode_record/1, record_to_ejson/1, ejson_to_record/2]).
-include("ts_db_records.hrl").
encode_record(Record) -> lists:flatten(json:encode(record_to_ejson(Record))).
record_to_ejson(Record=#ts_user{}) ->
{struct, [
{id, Record#ts_user.username},
{name, Record#ts_user.name},
{email, Record#ts_user.email},
{join_date, encode_datetime(Record#ts_user.join_date)},
{ext_data, Record#ts_user.ext_data}]};
record_to_ejson(Record=#ts_timeline{}) ->
% pull out the username and timeline id
{Username, TimelineId} = Record#ts_timeline.ref,
% create the EJSON struct
{struct, [
{user_id, Username},
{id, TimelineId},
{created, encode_datetime(Record#ts_timeline.created)},
{description, Record#ts_timeline.desc}]};
record_to_ejson(Record=#ts_entry{}) ->
% pull out the username, timeline id, and entry id
{Username, TimelineId, EntryId} = Record#ts_entry.ref,
% convert the timestamp to a date-time
DateTime = calendar:gregorian_seconds_to_datetime(Record#ts_entry.timestamp),
% create the EJSON struct
{struct, [
{user_id, Username},
{timeline_id, TimelineId},
{id, EntryId},
{timestamp, encode_datetime(DateTime)},
{mark, Record#ts_entry.mark},
{notes, Record#ts_entry.notes}]}.
encode_datetime({{Year, Month, Day}, {Hour, Minute, Second}}) ->
lists:flatten(io_lib:format("~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~2.10.0B.~3.10.0BZ",
[Year, Month, Day, Hour, Minute, Second, 000])).
ejson_to_record(_Empty=#ts_timeline{}, EJSON) ->
{struct, Fields} = EJSON,
#ts_timeline{
ref = {undefined, undefined},
created = decode_datetime(element(2, lists:keyfind(created, 1, Fields))),
desc = element(2, lists:keyfind(description, 1, Fields))};
ejson_to_record(_Empty=#ts_entry{}, EJSON) ->
{struct, Fields} = EJSON,
#ts_entry{
ref = {undefined, undefined, undefined},
timestamp = calendar:datetime_to_gregorian_seconds(decode_datetime(
element(2, lists:keyfind(timestamp, 1, Fields)))),
mark = element(2, lists:keyfind(mark, 1, Fields)),
notes = element(2, lists:keyfind(notes, 1, Fields))}.
decode_datetime(DateTimeString) ->
% TODO: catch badmatch and badarg on whole function
[DateString, TimeString] = re:split(DateTimeString, "[TZ]",
[{return, list}, trim]),
[YearString, MonthString, DayString] =
re:split(DateString, "-", [{return, list}]),
[HourString, MinuteString, SecondString] =
case re:split(TimeString, "[:\\.]", [{return, list}]) of
[HS, MS, SS, _MSS] -> [HS, MS, SS];
[HS, MS, SS] -> [HS, MS, SS]
end,
Date = {list_to_integer(YearString), list_to_integer(MonthString),
list_to_integer(DayString)},
Time = {list_to_integer(HourString), list_to_integer(MinuteString),
list_to_integer(SecondString)},
{Date, Time}.