From 78f48db162e2229a197b80c3dfa2bf2748b54676 Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Wed, 13 Aug 2014 23:32:19 -0700 Subject: [PATCH] parser (and encoder) accept `calendar:datetime()` tuples and convert into iso8601 strings --- CHANGES.md | 1 + README.md | 10 ++++++++++ src/jsx.erl | 6 ++++-- src/jsx_parser.erl | 19 +++++++++++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0503069..40f7912 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,7 @@ v2.1 * force the end of streams with `end_json` in addition to `end_stream` +* support for encoding erlang datetime tuples to iso8601 format v2.0.4 diff --git a/README.md b/README.md index 7b94bd9..a4a55b3 100644 --- a/README.md +++ b/README.md @@ -185,6 +185,7 @@ to understand and they prevented evolution of the encoding and decoding code `true`, `false` and `null` | `true`, `false` and `null` `array` | `[]` and `[JSON]` `object` | `#{}`, `[{}]` and `[{binary() OR atom() OR integer(), JSON}]` +see below | `datetime()` * numbers @@ -253,6 +254,13 @@ to understand and they prevented evolution of the encoding and decoding code keys are tolerated in json text decoded to erlang terms but are not allowed in erlang terms encoded to json +* datetime + + erlang datetime tuples (`{{Year, Month, Day}, {Hour, Min, Sec}}`) as returned + from `erlang:localtime/0` are automatically encoded as [iso8601][iso8601] + strings. no conversion is attempted of json [iso8601][iso8601] strings in + decoded json + ### incomplete input ### @@ -297,6 +305,7 @@ json_term() = [json_term()] | float() | binary() | atom() + | datetime() ``` the erlang representation of json. binaries should be `utf8` encoded, or close @@ -687,3 +696,4 @@ jsx wouldn't be what it is without the contributions of [paul davis](https://git [rfc4627]: http://tools.ietf.org/html/rfc4627 [travis]: https://travis-ci.org/ [jsxn]: https://github.com/talentdeficit/jsxn +[iso8601]: http://www.iso.org/iso/iso8601 diff --git a/src/jsx.erl b/src/jsx.erl index 7c574db..b2405c3 100644 --- a/src/jsx.erl +++ b/src/jsx.erl @@ -46,7 +46,8 @@ | [json_term()] | [] | true | false | null | integer() | float() - | binary() | atom(). + | binary() | atom() + | calendar:datetime(). -endif. -ifdef(maps_support). @@ -55,7 +56,8 @@ | map() | true | false | null | integer() | float() - | binary() | atom(). + | binary() | atom() + | calendar:datetime(). -endif. -type json_text() :: binary(). diff --git a/src/jsx_parser.erl b/src/jsx_parser.erl index 7c9af6b..c0aa38e 100644 --- a/src/jsx_parser.erl +++ b/src/jsx_parser.erl @@ -119,6 +119,16 @@ value([String|Tokens], Handler, Stack, Config) when is_atom(String) -> value([{string, atom_to_binary(String, utf8)}] ++ Tokens, Handler, Stack, Config); value([{raw, Raw}|Tokens], Handler, Stack, Config) when is_binary(Raw) -> value((jsx:decoder(?MODULE, [], []))(Raw) ++ Tokens, Handler, Stack, Config); +value([{{Year, Month, Day}, {Hour, Min, Sec}}|Tokens], Handler, Stack, Config) +when is_integer(Year), is_integer(Month), is_integer(Day), is_integer(Hour), is_integer(Min), is_integer(Sec) -> + value([{string, unicode:characters_to_binary(io_lib:format( + "~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~2.10.0B", + [Year, Month, Day, Hour, Min, Sec] + ))}|Tokens], + Handler, + Stack, + Config + ); value([], Handler, Stack, Config) -> incomplete(value, Handler, Stack, Config); value(BadTokens, Handler, Stack, Config) when is_list(BadTokens) -> @@ -1028,4 +1038,13 @@ repeated_key_test_() -> )} ]. + +datetime_test_() -> + [ + {"datetime", ?_assertEqual( + [start_array, {string, <<"2014-08-13T23:12:34">>}, end_array, end_json], + parse([start_array, {{2014,08,13},{23,12,34}}, end_array, end_json], []) + )} + ]. + -endif.