|
@@ -1,209 +1,337 @@
|
|
-module(rest).
|
|
-module(rest).
|
|
|
|
+
|
|
-author('Dmitry Bushmelev').
|
|
-author('Dmitry Bushmelev').
|
|
|
|
+
|
|
-behaviour(application).
|
|
-behaviour(application).
|
|
|
|
+
|
|
-behaviour(supervisor).
|
|
-behaviour(supervisor).
|
|
--export([init/1,start/2, stop/1]).
|
|
|
|
--export([behaviour_info/1, parse_transform/2, generate_to_json/3, binarize/1,
|
|
|
|
- generate_from_json/3, from_json/2, to_json/1, to_binary/1, parse/1, atomize/1]).
|
|
|
|
|
|
+
|
|
|
|
+-export([init/1, start/2, stop/1]).
|
|
|
|
+
|
|
|
|
+-export([behaviour_info/1,
|
|
|
|
+ parse_transform/2,
|
|
|
|
+ generate_to_json/3,
|
|
|
|
+ binarize/1,
|
|
|
|
+ generate_from_json/3,
|
|
|
|
+ from_json/2,
|
|
|
|
+ to_json/1,
|
|
|
|
+ to_binary/1,
|
|
|
|
+ parse/1,
|
|
|
|
+ atomize/1]).
|
|
|
|
|
|
stop(_State) -> ok.
|
|
stop(_State) -> ok.
|
|
-start(_StartType, _StartArgs) -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
|
|
|
|
|
+
|
|
|
|
+start(_StartType, _StartArgs) ->
|
|
|
|
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
|
|
|
+
|
|
init([]) ->
|
|
init([]) ->
|
|
- users:init(),
|
|
|
|
- kvs:join(),
|
|
|
|
- cowboy:start_clear(http, [{port,application:get_env(n2o,port,8005)}],
|
|
|
|
- #{env=>#{dispatch=> points() }}),
|
|
|
|
- {ok, {{one_for_one, 5, 10}, []}}.
|
|
|
|
-
|
|
|
|
-points() -> cowboy_router:compile([{'_', [
|
|
|
|
- {"/rest/kvs/0/[...]", rest_kvs, []},
|
|
|
|
- {"/rest/kvs/1/:id/[...]", rest_kvs, []},
|
|
|
|
- {"/rest/:resource", rest_cowboy, []},
|
|
|
|
- {"/rest/:resource/:id", rest_cowboy, []}
|
|
|
|
- ]}]).
|
|
|
|
-
|
|
|
|
-behaviour_info(callbacks) -> [{exists, 1}, {get, 0}, {get, 1}, {post, 1}, {delete, 1}, {from_json, 2}, {to_json, 1}];
|
|
|
|
|
|
+ users:init(),
|
|
|
|
+ kvs:join(),
|
|
|
|
+ cowboy:start_clear(http,
|
|
|
|
+ [{port, application:get_env(n2o, port, 8005)}],
|
|
|
|
+ #{env => #{dispatch => points()}}),
|
|
|
|
+ {ok, {{one_for_one, 5, 10}, []}}.
|
|
|
|
+
|
|
|
|
+points() ->
|
|
|
|
+ cowboy_router:compile([{'_',
|
|
|
|
+ [{"/rest/kvs/0/[...]", rest_kvs, []},
|
|
|
|
+ {"/rest/kvs/1/:id/[...]", rest_kvs, []},
|
|
|
|
+ {"/rest/:resource", rest_cowboy, []},
|
|
|
|
+ {"/rest/:resource/:id", rest_cowboy, []}]}]).
|
|
|
|
+
|
|
|
|
+behaviour_info(callbacks) ->
|
|
|
|
+ [{exists, 1},
|
|
|
|
+ {get, 0},
|
|
|
|
+ {get, 1},
|
|
|
|
+ {post, 1},
|
|
|
|
+ {delete, 1},
|
|
|
|
+ {from_json, 2},
|
|
|
|
+ {to_json, 1}];
|
|
behaviour_info(_) -> undefined.
|
|
behaviour_info(_) -> undefined.
|
|
|
|
|
|
parse_transform(Forms, _Options) ->
|
|
parse_transform(Forms, _Options) ->
|
|
RecordName = rest_record(Forms),
|
|
RecordName = rest_record(Forms),
|
|
RecordFields = record_fields(RecordName, Forms),
|
|
RecordFields = record_fields(RecordName, Forms),
|
|
- Forms1 = generate({from_json, 2}, RecordName, RecordFields, Forms),
|
|
|
|
- Forms2 = generate({to_json, 1}, RecordName, RecordFields, Forms1),
|
|
|
|
|
|
+ Forms1 = generate({from_json, 2},
|
|
|
|
+ RecordName,
|
|
|
|
+ RecordFields,
|
|
|
|
+ Forms),
|
|
|
|
+ Forms2 = generate({to_json, 1},
|
|
|
|
+ RecordName,
|
|
|
|
+ RecordFields,
|
|
|
|
+ Forms1),
|
|
Forms2.
|
|
Forms2.
|
|
|
|
|
|
rest_record([]) -> [];
|
|
rest_record([]) -> [];
|
|
-rest_record([{attribute, _, rest_record, RecordName} | _Forms]) -> RecordName;
|
|
|
|
|
|
+rest_record([{attribute, _, rest_record, RecordName}
|
|
|
|
+ | _Forms]) ->
|
|
|
|
+ RecordName;
|
|
rest_record([_ | Forms]) -> rest_record(Forms).
|
|
rest_record([_ | Forms]) -> rest_record(Forms).
|
|
|
|
|
|
-record_field({record_field, _, {atom, _, Field} },_cordName) ->
|
|
|
|
-% io:format("Case 1: ~p~n",[Field]),
|
|
|
|
- Field;
|
|
|
|
-record_field({record_field, _, {atom, _, Field}, Type},_cordName) ->
|
|
|
|
-% io:format("Case 2: ~p~n",[Field]),
|
|
|
|
- Field;
|
|
|
|
-record_field({typed_record_field, {record_field,_,{atom, _, Field},_}, Type},RecordName) ->
|
|
|
|
- Rec = allow(Type),
|
|
|
|
- put({RecordName,Field},Rec),
|
|
|
|
-% case Rec of
|
|
|
|
-% undefined -> io:format("Case 3: ~p~n",[Field]);
|
|
|
|
-% _ -> io:format("Case 3: ~p, Link: ~p~n",[Field,Rec]) end,
|
|
|
|
- Field.
|
|
|
|
-
|
|
|
|
-allow({type,_,union,Components}) -> findType(Components);
|
|
|
|
|
|
+record_field({record_field, _, {atom, _, Field}},
|
|
|
|
+ _cordName) ->
|
|
|
|
+ % io:format("Case 1: ~p~n",[Field]),
|
|
|
|
+ Field;
|
|
|
|
+record_field({record_field, _, {atom, _, Field}, Type},
|
|
|
|
+ _cordName) ->
|
|
|
|
+ % io:format("Case 2: ~p~n",[Field]),
|
|
|
|
+ Field;
|
|
|
|
+record_field({typed_record_field,
|
|
|
|
+ {record_field, _, {atom, _, Field}, _},
|
|
|
|
+ Type},
|
|
|
|
+ RecordName) ->
|
|
|
|
+ Rec = allow(Type),
|
|
|
|
+ put({RecordName, Field}, Rec),
|
|
|
|
+ % case Rec of
|
|
|
|
+ % undefined -> io:format("Case 3: ~p~n",[Field]);
|
|
|
|
+ % _ -> io:format("Case 3: ~p, Link: ~p~n",[Field,Rec]) end,
|
|
|
|
+ Field.
|
|
|
|
+
|
|
|
|
+allow({type, _, union, Components}) ->
|
|
|
|
+ findType(Components);
|
|
allow(Type) -> findType([Type]).
|
|
allow(Type) -> findType([Type]).
|
|
|
|
|
|
findType([]) -> undefined;
|
|
findType([]) -> undefined;
|
|
-findType([{type,_,record,[{atom,_,X}]}|T]) -> X;
|
|
|
|
-findType([{remote_type,_,[{atom,_,_},{atom,_,X},_]}|T]) -> X;
|
|
|
|
-findType([H|T]) ->
|
|
|
|
-% io:format("Unknown Type: ~p~n",[H]),
|
|
|
|
- findType(T).
|
|
|
|
-
|
|
|
|
-record_fields(RecordName, [{attribute, _, record, {RecordName, Fields}} | _Forms]) ->
|
|
|
|
- [record_field(Field,RecordName) || Field <- Fields];
|
|
|
|
-record_fields(RecordName, [_ | Forms]) -> record_fields(RecordName, Forms);
|
|
|
|
|
|
+findType([{type, _, record, [{atom, _, X}]} | T]) -> X;
|
|
|
|
+findType([{remote_type,
|
|
|
|
+ _,
|
|
|
|
+ [{atom, _, _}, {atom, _, X}, _]}
|
|
|
|
+ | T]) ->
|
|
|
|
+ X;
|
|
|
|
+findType([H | T]) ->
|
|
|
|
+ % io:format("Unknown Type: ~p~n",[H]),
|
|
|
|
+ findType(T).
|
|
|
|
+
|
|
|
|
+record_fields(RecordName,
|
|
|
|
+ [{attribute, _, record, {RecordName, Fields}}
|
|
|
|
+ | _Forms]) ->
|
|
|
|
+ [record_field(Field, RecordName) || Field <- Fields];
|
|
|
|
+record_fields(RecordName, [_ | Forms]) ->
|
|
|
|
+ record_fields(RecordName, Forms);
|
|
record_fields(__cordName, []) -> [].
|
|
record_fields(__cordName, []) -> [].
|
|
|
|
|
|
last_export_line(Exports) ->
|
|
last_export_line(Exports) ->
|
|
case lists:reverse(Exports) of
|
|
case lists:reverse(Exports) of
|
|
- [{_, Line, _, _} | _] -> Line;
|
|
|
|
- _ -> 0 end.
|
|
|
|
|
|
+ [{_, Line, _, _} | _] -> Line;
|
|
|
|
+ _ -> 0
|
|
|
|
+ end.
|
|
|
|
|
|
-generate({FunName, _Arity} = Fun, Record, Fields, Forms) ->
|
|
|
|
- Exports = lists:filter(fun({attribute, _, export, _}) -> true; (_) -> false end, Forms),
|
|
|
|
|
|
+generate({FunName, _Arity} = Fun, Record, Fields,
|
|
|
|
+ Forms) ->
|
|
|
|
+ Exports = lists:filter(fun ({attribute,
|
|
|
|
+ _,
|
|
|
|
+ export,
|
|
|
|
+ _}) ->
|
|
|
|
+ true;
|
|
|
|
+ (_) -> false
|
|
|
|
+ end,
|
|
|
|
+ Forms),
|
|
case exported(Fun, Exports) of
|
|
case exported(Fun, Exports) of
|
|
- true -> Forms;
|
|
|
|
|
|
+ true -> Forms;
|
|
false ->
|
|
false ->
|
|
Line = last_export_line(Exports),
|
|
Line = last_export_line(Exports),
|
|
- Gen = list_to_atom("generate_" ++ atom_to_list(FunName)),
|
|
|
|
- lists:flatten([?MODULE:Gen(export(Form, Fun, Line), Record, Fields) || Form <- Forms])
|
|
|
|
|
|
+ Gen = list_to_atom("generate_" ++
|
|
|
|
+ atom_to_list(FunName)),
|
|
|
|
+ lists:flatten([(?MODULE):Gen(export(Form, Fun, Line),
|
|
|
|
+ Record,
|
|
|
|
+ Fields)
|
|
|
|
+ || Form <- Forms])
|
|
end.
|
|
end.
|
|
|
|
|
|
-exported(Fun, Exports) -> lists:member(Fun, lists:flatten([E || {attribute, _, export, E} <- Exports])).
|
|
|
|
|
|
+exported(Fun, Exports) ->
|
|
|
|
+ lists:member(Fun,
|
|
|
|
+ lists:flatten([E
|
|
|
|
+ || {attribute, _, export, E} <- Exports])).
|
|
|
|
|
|
-field_var(Field) -> list_to_atom("V_" ++ atom_to_list(Field)).
|
|
|
|
|
|
+field_var(Field) ->
|
|
|
|
+ list_to_atom("V_" ++ atom_to_list(Field)).
|
|
|
|
|
|
from_json_prelude(Line) ->
|
|
from_json_prelude(Line) ->
|
|
- {clause, Line,
|
|
|
|
|
|
+ {clause,
|
|
|
|
+ Line,
|
|
[{nil, Line}, {var, Line, 'Acc'}],
|
|
[{nil, Line}, {var, Line, 'Acc'}],
|
|
[],
|
|
[],
|
|
[{var, Line, 'Acc'}]}.
|
|
[{var, Line, 'Acc'}]}.
|
|
|
|
|
|
from_json_coda(Line) ->
|
|
from_json_coda(Line) ->
|
|
- {clause, Line,
|
|
|
|
- [{cons, Line, {var, Line, '_'}, {var, Line, 'Json'}}, {var, Line, 'Acc'}],
|
|
|
|
|
|
+ {clause,
|
|
|
|
+ Line,
|
|
|
|
+ [{cons, Line, {var, Line, '_'}, {var, Line, 'Json'}},
|
|
|
|
+ {var, Line, 'Acc'}],
|
|
[],
|
|
[],
|
|
- [{call, Line, {atom, Line, from_json}, [
|
|
|
|
-% {var, Line, 'Json'} % here is fix for recursive binarized preprocessing to raw X:from_json
|
|
|
|
- {call,Line,{remote,Line,{atom,Line,?MODULE},{atom,Line,binarize}},[{var, Line, 'Json'}]}
|
|
|
|
- , {var, Line, 'Acc'}]}]}.
|
|
|
|
|
|
+ [{call,
|
|
|
|
+ Line,
|
|
|
|
+ {atom, Line, from_json},
|
|
|
|
+ [% {var, Line, 'Json'} % here is fix for recursive binarized preprocessing to raw X:from_json
|
|
|
|
+ {call,
|
|
|
|
+ Line,
|
|
|
|
+ {remote,
|
|
|
|
+ Line,
|
|
|
|
+ {atom, Line, ?MODULE},
|
|
|
|
+ {atom, Line, binarize}},
|
|
|
|
+ [{var, Line, 'Json'}]},
|
|
|
|
+ {var, Line, 'Acc'}]}]}.
|
|
|
|
|
|
from_json_clauses(_, _, []) -> [];
|
|
from_json_clauses(_, _, []) -> [];
|
|
from_json_clauses(Line, Record, [Field | Fields]) ->
|
|
from_json_clauses(Line, Record, [Field | Fields]) ->
|
|
- [{clause, Line,
|
|
|
|
- [{cons, Line,
|
|
|
|
- {tuple, Line,
|
|
|
|
- [{bin, Line,
|
|
|
|
- [{bin_element, Line, {string, Line, atom_to_list(Field)}, default, default}]},
|
|
|
|
|
|
+ [{clause,
|
|
|
|
+ Line,
|
|
|
|
+ [{cons,
|
|
|
|
+ Line,
|
|
|
|
+ {tuple,
|
|
|
|
+ Line,
|
|
|
|
+ [{bin,
|
|
|
|
+ Line,
|
|
|
|
+ [{bin_element,
|
|
|
|
+ Line,
|
|
|
|
+ {string, Line, atom_to_list(Field)},
|
|
|
|
+ default,
|
|
|
|
+ default}]},
|
|
{var, Line, field_var(Field)}]},
|
|
{var, Line, field_var(Field)}]},
|
|
{var, Line, 'Json'}},
|
|
{var, Line, 'Json'}},
|
|
{var, Line, 'Acc'}],
|
|
{var, Line, 'Acc'}],
|
|
[],
|
|
[],
|
|
- [{call, Line,
|
|
|
|
|
|
+ [{call,
|
|
|
|
+ Line,
|
|
{atom, Line, from_json},
|
|
{atom, Line, from_json},
|
|
[{var, Line, 'Json'},
|
|
[{var, Line, 'Json'},
|
|
- {record, Line,
|
|
|
|
|
|
+ {record,
|
|
|
|
+ Line,
|
|
{var, Line, 'Acc'},
|
|
{var, Line, 'Acc'},
|
|
Record,
|
|
Record,
|
|
- [{record_field, Line,
|
|
|
|
|
|
+ [{record_field,
|
|
|
|
+ Line,
|
|
{atom, Line, Field},
|
|
{atom, Line, Field},
|
|
- {call, Line,
|
|
|
|
- {remote, Line, {atom, Line, ?MODULE }, {atom, Line, from_json}},
|
|
|
|
|
|
+ {call,
|
|
|
|
+ Line,
|
|
|
|
+ {remote,
|
|
|
|
+ Line,
|
|
|
|
+ {atom, Line, ?MODULE},
|
|
|
|
+ {atom, Line, from_json}},
|
|
[{var, Line, field_var(Field)},
|
|
[{var, Line, field_var(Field)},
|
|
- {atom,Line, case get({Record,Field}) of undefined -> Record; FieldType -> FieldType end}]}
|
|
|
|
- }]}]}]}
|
|
|
|
|
|
+ {atom,
|
|
|
|
+ Line,
|
|
|
|
+ case get({Record, Field}) of
|
|
|
|
+ undefined -> Record;
|
|
|
|
+ FieldType -> FieldType
|
|
|
|
+ end}]}}]}]}]}
|
|
| from_json_clauses(Line, Record, Fields)].
|
|
| from_json_clauses(Line, Record, Fields)].
|
|
|
|
|
|
generate_from_json({eof, Line}, Record, Fields) ->
|
|
generate_from_json({eof, Line}, Record, Fields) ->
|
|
- [{function, Line, from_json, 2,
|
|
|
|
- [from_json_prelude(Line)] ++ from_json_clauses(Line, Record, Fields) ++ [from_json_coda(Line)]},
|
|
|
|
|
|
+ [{function,
|
|
|
|
+ Line,
|
|
|
|
+ from_json,
|
|
|
|
+ 2,
|
|
|
|
+ [from_json_prelude(Line)] ++
|
|
|
|
+ from_json_clauses(Line, Record, Fields) ++
|
|
|
|
+ [from_json_coda(Line)]},
|
|
{eof, Line + 1}];
|
|
{eof, Line + 1}];
|
|
generate_from_json(Form, _, _) -> Form.
|
|
generate_from_json(Form, _, _) -> Form.
|
|
|
|
|
|
-export({attribute, LastExportLine, export, Exports}, Fun, LastExportLine) ->
|
|
|
|
|
|
+export({attribute, LastExportLine, export, Exports},
|
|
|
|
+ Fun, LastExportLine) ->
|
|
{attribute, LastExportLine, export, [Fun | Exports]};
|
|
{attribute, LastExportLine, export, [Fun | Exports]};
|
|
export(Form, _, _) -> Form.
|
|
export(Form, _, _) -> Form.
|
|
|
|
|
|
to_json_cons(Line, []) -> {nil, Line};
|
|
to_json_cons(Line, []) -> {nil, Line};
|
|
to_json_cons(Line, [Field | Fields]) ->
|
|
to_json_cons(Line, [Field | Fields]) ->
|
|
- {cons, Line,
|
|
|
|
- {tuple, Line,
|
|
|
|
|
|
+ {cons,
|
|
|
|
+ Line,
|
|
|
|
+ {tuple,
|
|
|
|
+ Line,
|
|
[{atom, Line, Field},
|
|
[{atom, Line, Field},
|
|
- {call, Line,
|
|
|
|
- {remote, Line, {atom, Line, ?MODULE}, {atom, Line, to_json}},
|
|
|
|
|
|
+ {call,
|
|
|
|
+ Line,
|
|
|
|
+ {remote,
|
|
|
|
+ Line,
|
|
|
|
+ {atom, Line, ?MODULE},
|
|
|
|
+ {atom, Line, to_json}},
|
|
[{var, Line, field_var(Field)}]}]},
|
|
[{var, Line, field_var(Field)}]}]},
|
|
to_json_cons(Line, Fields)}.
|
|
to_json_cons(Line, Fields)}.
|
|
|
|
|
|
generate_to_json({eof, Line}, Record, Fields) ->
|
|
generate_to_json({eof, Line}, Record, Fields) ->
|
|
- [{function, Line, to_json, 1,
|
|
|
|
- [{clause, Line,
|
|
|
|
- [{record, Line, Record,
|
|
|
|
- [{record_field, Line, {atom, Line, F}, {var, Line, field_var(F)}} || F <- Fields]}],
|
|
|
|
|
|
+ [{function,
|
|
|
|
+ Line,
|
|
|
|
+ to_json,
|
|
|
|
+ 1,
|
|
|
|
+ [{clause,
|
|
|
|
+ Line,
|
|
|
|
+ [{record,
|
|
|
|
+ Line,
|
|
|
|
+ Record,
|
|
|
|
+ [{record_field,
|
|
|
|
+ Line,
|
|
|
|
+ {atom, Line, F},
|
|
|
|
+ {var, Line, field_var(F)}}
|
|
|
|
+ || F <- Fields]}],
|
|
[],
|
|
[],
|
|
[to_json_cons(Line, Fields)]}]},
|
|
[to_json_cons(Line, Fields)]}]},
|
|
{eof, Line + 1}];
|
|
{eof, Line + 1}];
|
|
-
|
|
|
|
generate_to_json(Form, _, _) -> Form.
|
|
generate_to_json(Form, _, _) -> Form.
|
|
|
|
|
|
-from_json(<<Data/binary>>,_) ->
|
|
|
|
- binary_to_list(Data);
|
|
|
|
-from_json({struct, Props},X) ->
|
|
|
|
- from_json(Props,X);
|
|
|
|
-from_json([{Key,_}|_]=Props,X) when Key =/= struct ->
|
|
|
|
- X:from_json(binarize(Props),X:new());
|
|
|
|
-from_json(Any,X) ->
|
|
|
|
- Any.
|
|
|
|
-
|
|
|
|
-atomize([{Key,_}|_]=Props) when Key =/= struct ->
|
|
|
|
- lists:map(fun ({K,V}) when is_atom(K) -> {K,V};
|
|
|
|
- ({K,V}) when is_binary(K) -> {list_to_existing_atom(binary_to_list(K)),V} end, Props);
|
|
|
|
|
|
+from_json(<<Data/binary>>, _) -> binary_to_list(Data);
|
|
|
|
+from_json({struct, Props}, X) -> from_json(Props, X);
|
|
|
|
+from_json([{Key, _} | _] = Props, X)
|
|
|
|
+ when Key =/= struct ->
|
|
|
|
+ X:from_json(binarize(Props), X:new());
|
|
|
|
+from_json(Any, X) -> Any.
|
|
|
|
+
|
|
|
|
+atomize([{Key, _} | _] = Props) when Key =/= struct ->
|
|
|
|
+ lists:map(fun ({K, V}) when is_atom(K) -> {K, V};
|
|
|
|
+ ({K, V}) when is_binary(K) ->
|
|
|
|
+ {list_to_existing_atom(binary_to_list(K)), V}
|
|
|
|
+ end,
|
|
|
|
+ Props);
|
|
atomize(X) -> X.
|
|
atomize(X) -> X.
|
|
|
|
|
|
-binarize([{Key,_}|_]=Props) when Key =/= struct ->
|
|
|
|
- lists:map(fun ({K,V}) when is_atom(K) -> {list_to_binary(atom_to_list(K)),allowed_value(V)};
|
|
|
|
- ({K,V}) when is_binary(K) -> {K,allowed_value(V)} end, Props);
|
|
|
|
|
|
+binarize([{Key, _} | _] = Props) when Key =/= struct ->
|
|
|
|
+ lists:map(fun ({K, V}) when is_atom(K) ->
|
|
|
|
+ {list_to_binary(atom_to_list(K)), allowed_value(V)};
|
|
|
|
+ ({K, V}) when is_binary(K) -> {K, allowed_value(V)}
|
|
|
|
+ end,
|
|
|
|
+ Props);
|
|
binarize(X) -> X.
|
|
binarize(X) -> X.
|
|
|
|
|
|
allowed_value(X) when is_reference(X) -> [];
|
|
allowed_value(X) when is_reference(X) -> [];
|
|
allowed_value(X) -> X.
|
|
allowed_value(X) -> X.
|
|
|
|
|
|
-to_json(X) when is_tuple(X) -> Module = hd(tuple_to_list(X)), Module:to_json(X);
|
|
|
|
|
|
+to_json(X) when is_tuple(X) ->
|
|
|
|
+ Module = hd(tuple_to_list(X)),
|
|
|
|
+ Module:to_json(X);
|
|
to_json(Data) ->
|
|
to_json(Data) ->
|
|
case is_string(Data) of
|
|
case is_string(Data) of
|
|
- true -> rest:to_binary(Data);
|
|
|
|
|
|
+ true -> rest:to_binary(Data);
|
|
false -> json_match(Data)
|
|
false -> json_match(Data)
|
|
end.
|
|
end.
|
|
|
|
|
|
json_match([{_, _} | _] = Props) ->
|
|
json_match([{_, _} | _] = Props) ->
|
|
- [ {rest:to_binary(Key), to_json(Value)} || {Key, Value} <- Props];
|
|
|
|
-json_match([_ | _] = NonEmptyList) -> [to_json(X) || X <- NonEmptyList];
|
|
|
|
|
|
+ [{rest:to_binary(Key), to_json(Value)}
|
|
|
|
+ || {Key, Value} <- Props];
|
|
|
|
+json_match([_ | _] = NonEmptyList) ->
|
|
|
|
+ [to_json(X) || X <- NonEmptyList];
|
|
json_match(Any) -> Any.
|
|
json_match(Any) -> Any.
|
|
|
|
|
|
-is_char(C) -> is_integer(C) andalso C >= 0 andalso C =< 255.
|
|
|
|
|
|
+is_char(C) ->
|
|
|
|
+ is_integer(C) andalso C >= 0 andalso C =< 255.
|
|
|
|
|
|
-is_string([N | _] = PossibleString) when is_number(N) -> lists:all(fun is_char/1, PossibleString);
|
|
|
|
-is_string(_) -> false.
|
|
|
|
|
|
+is_string([N | _] = PossibleString) when is_number(N) ->
|
|
|
|
+ lists:all(fun is_char/1, PossibleString);
|
|
|
|
+is_string(_) -> false.
|
|
|
|
|
|
-to_binary(A) when is_atom(A) -> atom_to_binary(A,latin1);
|
|
|
|
|
|
+to_binary(A) when is_atom(A) ->
|
|
|
|
+ atom_to_binary(A, latin1);
|
|
to_binary(B) when is_binary(B) -> B;
|
|
to_binary(B) when is_binary(B) -> B;
|
|
-to_binary(I) when is_integer(I) -> to_binary(integer_to_list(I));
|
|
|
|
-to_binary(F) when is_float(F) -> float_to_binary(F,[{decimals,9},compact]);
|
|
|
|
-to_binary(L) when is_list(L) -> iolist_to_binary(L).
|
|
|
|
|
|
+to_binary(I) when is_integer(I) ->
|
|
|
|
+ to_binary(integer_to_list(I));
|
|
|
|
+to_binary(F) when is_float(F) ->
|
|
|
|
+ float_to_binary(F, [{decimals, 9}, compact]);
|
|
|
|
+to_binary(L) when is_list(L) -> iolist_to_binary(L).
|
|
|
|
|
|
-parse(String) when is_binary(String) -> parse(binary_to_list(String));
|
|
|
|
|
|
+parse(String) when is_binary(String) ->
|
|
|
|
+ parse(binary_to_list(String));
|
|
parse(String) ->
|
|
parse(String) ->
|
|
- {ok,Tokens,_EndLine} = erl_scan:string(String ++ "."),
|
|
|
|
- {ok,AbsForm} = erl_parse:parse_exprs(Tokens),
|
|
|
|
- {value,Value,_Bs} = erl_eval:exprs(AbsForm, erl_eval:new_bindings()),
|
|
|
|
|
|
+ {ok, Tokens, _EndLine} = erl_scan:string(String ++ "."),
|
|
|
|
+ {ok, AbsForm} = erl_parse:parse_exprs(Tokens),
|
|
|
|
+ {value, Value, _Bs} = erl_eval:exprs(AbsForm,
|
|
|
|
+ erl_eval:new_bindings()),
|
|
Value.
|
|
Value.
|