Permalink
Browse files

s/ejson/jiffy

Replace the use of the ejson module by jiffy and fallback to mochijson2
if the module can't be loaded.
  • Loading branch information...
1 parent 06d9451 commit d4574e4a7927090e8fb391c688dc201932eba1de @benoitc committed Aug 31, 2012
Showing with 81 additions and 29 deletions.
  1. +4 −4 rebar.config
  2. +15 −15 src/couchbeam.erl
  3. +52 −0 src/couchbeam_ejson.erl
  4. +1 −1 src/couchbeam_uuids.erl
  5. +9 −9 src/couchbeam_view.erl
View
@@ -5,17 +5,17 @@
]}.
{deps, [
- {mochiweb, ".*", {git,"http://github.com/mochi/mochiweb.git",
+ {mochiweb, ".*", {git,"http://github.com/mochi/mochiweb.git",
"HEAD"}},
-
+
%% ejson for JSON and header parsing
- {ejson, ".*", {git,"http://github.com/benoitc/ejson.git",
+ {jiffy, ".*", {git,"http://github.com/refuge/jiffy.git",
"master"}},
%% erlang-oauth for oauth authentification
{oauth, ".*", {git,"http://github.com/refuge/erlang-oauth.git",
"master"}},
-
+
%% ibrowse for doing HTTP requests
{ibrowse, ".*", {git, "http://github.com/cmullaparthi/ibrowse.git",
{branch, "master"}}}
View
@@ -138,7 +138,7 @@ server_info(#server{options=IbrowseOpts}=Server) ->
Url = binary_to_list(iolist_to_binary(server_url(Server))),
case couchbeam_httpc:request(get, Url, ["200"], IbrowseOpts) of
{ok, _Status, _Headers, Body} ->
- Version = ejson:decode(Body),
+ Version = couchbeam_ejson:decode(Body),
{ok, Version};
Error -> Error
end.
@@ -170,7 +170,7 @@ get_uuids(Server, Count) ->
replicate(#server{options=IbrowseOpts}=Server, RepObj) ->
Url = make_url(Server, "_replicate", []),
Headers = [{"Content-Type", "application/json"}],
- JsonObj = ejson:encode(RepObj),
+ JsonObj = couchbeam_ejson:encode(RepObj),
case couchbeam_httpc:request_stream({self(), once}, post, Url, IbrowseOpts, Headers,
JsonObj) of
@@ -208,7 +208,7 @@ all_dbs(#server{options=IbrowseOpts}=Server) ->
Url = make_url(Server, "_all_dbs", []),
case couchbeam_httpc:request(get, Url, ["200"], IbrowseOpts) of
{ok, _, _, Body} ->
- AllDbs = ejson:decode(Body),
+ AllDbs = couchbeam_ejson:decode(Body),
{ok, AllDbs};
Error ->
Error
@@ -307,7 +307,7 @@ delete_db(#server{options=IbrowseOpts}=Server, DbName) ->
Url = make_url(Server, dbname(DbName), []),
case couchbeam_httpc:request(delete, Url, ["200"], IbrowseOpts) of
{ok, _, _, Body} ->
- {ok, ejson:decode(Body)};
+ {ok, couchbeam_ejson:decode(Body)};
Error ->
Error
end.
@@ -318,7 +318,7 @@ db_info(#db{server=Server, name=DbName, options=IbrowseOpts}) ->
Url = make_url(Server, DbName, []),
case couchbeam_httpc:request(get, Url, ["200"], IbrowseOpts) of
{ok, _Status, _Headers, Body} ->
- Infos = ejson:decode(Body),
+ Infos = couchbeam_ejson:decode(Body),
{ok, Infos};
{error, {ok, "404", _, _}} ->
{error, db_not_found};
@@ -350,7 +350,7 @@ open_doc(#db{server=Server, options=IbrowseOpts}=Db, DocId, Params) ->
Url = make_url(Server, doc_url(Db, DocId1), Params),
case db_request(get, Url, ["200", "201"], IbrowseOpts) of
{ok, _, _, Body} ->
- {ok, ejson:decode(Body)};
+ {ok, couchbeam_ejson:decode(Body)};
Error ->
Error
end.
@@ -383,11 +383,11 @@ save_doc(#db{server=Server, options=IbrowseOpts}=Db, {Props}=Doc, Options) ->
couchbeam_util:encode_docid(DocId1)
end,
Url = make_url(Server, doc_url(Db, DocId), Options),
- Body = ejson:encode(Doc),
+ Body = couchbeam_ejson:encode(Doc),
Headers = [{"Content-Type", "application/json"}],
case db_request(put, Url, ["201", "202"], IbrowseOpts, Headers, Body) of
{ok, _, _, RespBody} ->
- {JsonProp} = ejson:decode(RespBody),
+ {JsonProp} = couchbeam_ejson:decode(RespBody),
NewRev = couchbeam_util:get_value(<<"rev">>, JsonProp),
NewDocId = couchbeam_util:get_value(<<"id">>, JsonProp),
Doc1 = couchbeam_doc:set_value(<<"_rev">>, NewRev,
@@ -453,21 +453,21 @@ save_docs(#db{server=Server, options=IbrowseOpts}=Db, Docs, Options) ->
{Options2, Body} = case couchbeam_util:get_value("all_or_nothing",
Options1, false) of
true ->
- Body1 = ejson:encode({[
+ Body1 = couchbeam_ejson:encode({[
{<<"all_or_nothing">>, true},
{<<"docs">>, Docs1}
]}),
{proplists:delete("all_or_nothing", Options1), Body1};
_ ->
- Body1 = ejson:encode({[{<<"docs">>, Docs1}]}),
+ Body1 = couchbeam_ejson:encode({[{<<"docs">>, Docs1}]}),
{Options1, Body1}
end,
Url = make_url(Server, [db_url(Db), "/", "_bulk_docs"], Options2),
Headers = [{"Content-Type", "application/json"}],
case db_request(post, Url, ["201"], IbrowseOpts, Headers, Body) of
{ok, _, _, RespBody} ->
- {ok, ejson:decode(RespBody)};
+ {ok, couchbeam_ejson:decode(RespBody)};
Error ->
Error
end.
@@ -588,7 +588,7 @@ put_attachment(#db{server=Server, options=IbrowseOpts}=Db, DocId, Name, Body, Op
case db_request(put, Url, ["201"], IbrowseOpts, FinalHeaders, Body) of
{ok, _, _, RespBody} ->
- {[{<<"ok">>, true}|R]} = ejson:decode(RespBody),
+ {[{<<"ok">>, true}|R]} = couchbeam_ejson:decode(RespBody),
{ok, {R}};
Error ->
Error
@@ -625,7 +625,7 @@ delete_attachment(#db{server=Server, options=IbrowseOpts}=Db, DocOrDocId, Name,
Url = make_url(Server, [db_url(Db), "/", DocId, "/", Name], Options2),
case db_request(delete, Url, ["200"], IbrowseOpts) of
{ok, _, _, RespBody} ->
- {[{<<"ok">>,true}|R]} = ejson:decode(RespBody),
+ {[{<<"ok">>,true}|R]} = couchbeam_ejson:decode(RespBody),
{ok, {R}};
Error ->
@@ -707,7 +707,7 @@ view(#db{server=Server}=Db, ViewName, Options) ->
undefined ->
{get, Options1, []};
Keys ->
- Body1 = ejson:encode({[{<<"keys">>, Keys}]}),
+ Body1 = couchbeam_ejson:encode({[{<<"keys">>, Keys}]}),
{post, proplists:delete("keys", Options1), Body1}
end,
Headers = case Method of
@@ -740,7 +740,7 @@ ensure_full_commit(#db{server=Server, options=IbrowseOpts}=Db, Options) ->
Headers = [{"Content-Type", "application/json"}],
case db_request(post, Url, ["201"], IbrowseOpts, Headers) of
{ok, _, _, Body} ->
- {[{<<"ok">>, true}|R]} = ejson:decode(Body),
+ {[{<<"ok">>, true}|R]} = couchbeam_ejson:decode(Body),
{ok, R};
Error ->
Error
View
@@ -0,0 +1,52 @@
+%%% -*- erlang -*-
+%%%
+%%% This file is part of couchbeam released under the MIT license.
+%%% See the NOTICE for more information.
+%%%
+
+-module(couchbeam_ejson).
+
+-export([encode/1, decode/1]).
+
+-include("couchbeam.hrl").
+
+-spec encode(ejson()) -> binary().
+%% @doc encode an erlang term to JSON. Throw an exception if there is
+%% any error.
+encode(D) ->
+ try
+ jiffy:encode(D, [uescape])
+ catch
+ error:{not_loaded, _} ->
+ erl_encode(D)
+ end.
+
+-spec decode(binary()) -> ejson().
+%% @doc decode a binary to an EJSON term. Throw an exception if there is
+%% any error.
+decode(D) ->
+ try
+ jiffy:decode(D)
+ catch
+ error:{not_loaded, _} ->
+ erl_decode(D);
+ throw:Error ->
+ throw({invalid_json, Error})
+ end.
+
+
+erl_decode(D) ->
+ try
+ (mochijson2:decoder([{object_hook, fun({struct, L}) -> {L}end}]))(D)
+ catch _Type:Error ->
+ throw({invalid_json, {Error, D}})
+ end.
+
+erl_encode(D) ->
+ Opts = [{handler, fun mochi_encode_handler/1}],
+ iolist_to_binary((mochijson2:encoder(Opts))(D)).
+
+mochi_encode_handler({L}) when is_list(L) ->
+ {struct, L};
+mochi_encode_handler(Bad) ->
+ exit({json_encode, {bad_term, Bad}}).
View
@@ -105,7 +105,7 @@ get_new_uuids(Server=#server{host=Host, port=Port,
Url = couchbeam:make_url(Server, "_uuids", [{"count", Count}]),
case couchbeam_httpc:request(get, Url, ["200"], IbrowseOptions) of
{ok, _Status, _Headers, Body} ->
- {[{<<"uuids">>, Uuids}]} = ejson:decode(Body),
+ {[{<<"uuids">>, Uuids}]} = couchbeam_ejson:decode(Body),
ServerUuids = #server_uuids{host_port={Host,
Port}, uuids=(Acc ++ Uuids)},
ets:insert(couchbeam_uuids, ServerUuids),
View
@@ -165,7 +165,7 @@ stream(#db{options=IbrowseOpts}=Db, ViewName, ClientPid, Options) ->
get ->
couchbeam_httpc:request_stream({ViewPid, once}, get, Url, IbrowseOpts);
post ->
- Body = ejson:encode({[{<<"keys">>, Args#view_query_args.keys}]}),
+ Body = couchbeam_ejson:encode({[{<<"keys">>, Args#view_query_args.keys}]}),
Headers = [{"Content-Type", "application/json"}],
couchbeam_httpc:request_stream({ViewPid, once}, post, Url,
IbrowseOpts, Headers, Body)
@@ -201,14 +201,14 @@ count(#db{options=IbrowseOpts}=Db, ViewName, Options)->
get ->
couchbeam_httpc:request(get, Url, ["200"], IbrowseOpts);
post ->
- Body = ejson:encode({[{<<"keys">>, Args#view_query_args.keys}]}),
+ Body = couchbeam_ejson:encode({[{<<"keys">>, Args#view_query_args.keys}]}),
Headers = [{"Content-Type", "application/json"}],
couchbeam_httpc:request_stream(post, Url, ["200"],
IbrowseOpts, Headers, Body)
end,
case Result of
{ok, _, _, RespBody} ->
- {Props} = ejson:decode(RespBody),
+ {Props} = couchbeam_ejson:decode(RespBody),
case proplists:get_value("limit",
Args#view_query_args.options, 0) of
0 ->
@@ -323,7 +323,7 @@ parse_view_options(Options) ->
parse_view_options([], Args) ->
Args;
parse_view_options([{key, Value}|Rest], #view_query_args{options=Opts}=Args) ->
- Opts1 = [{"key", ejson:encode(Value)}|Opts],
+ Opts1 = [{"key", couchbeam_ejson:encode(Value)}|Opts],
parse_view_options(Rest, Args#view_query_args{options=Opts1});
parse_view_options([{start_docid, Value}|Rest], #view_query_args{options=Opts}=Args) ->
Opts1 = [{"start_docid", Value}|Opts],
@@ -332,16 +332,16 @@ parse_view_options([{end_docid, Value}|Rest], #view_query_args{options=Opts}=Arg
Opts1 = [{"end_docid", Value}|Opts],
parse_view_options(Rest, Args#view_query_args{options=Opts1});
parse_view_options([{start_key, Value}|Rest], #view_query_args{options=Opts}=Args) ->
- Opts1 = [{"start_key", ejson:encode(Value)}|Opts],
+ Opts1 = [{"start_key", couchbeam_ejson:encode(Value)}|Opts],
parse_view_options(Rest, Args#view_query_args{options=Opts1});
parse_view_options([{end_key, Value}|Rest], #view_query_args{options=Opts}=Args) ->
- Opts1 = [{"end_key", ejson:encode(Value)}|Opts],
+ Opts1 = [{"end_key", couchbeam_ejson:encode(Value)}|Opts],
parse_view_options(Rest, Args#view_query_args{options=Opts1});
parse_view_options([{startkey, Value}|Rest], #view_query_args{options=Opts}=Args) ->
- Opts1 = [{"startkey", ejson:encode(Value)}|Opts],
+ Opts1 = [{"startkey", couchbeam_ejson:encode(Value)}|Opts],
parse_view_options(Rest, Args#view_query_args{options=Opts1});
parse_view_options([{endkey, Value}|Rest], #view_query_args{options=Opts}=Args) ->
- Opts1 = [{"endkey", ejson:encode(Value)}|Opts],
+ Opts1 = [{"endkey", couchbeam_ejson:encode(Value)}|Opts],
parse_view_options(Rest, Args#view_query_args{options=Opts1});
parse_view_options([{limit, Value}|Rest], #view_query_args{options=Opts}=Args) ->
Opts1 = [{"limit", Value}|Opts],
@@ -542,7 +542,7 @@ do_redirect(Headers, UserFun, Callback, {Args, Url, IbrowseOpts}) ->
get ->
couchbeam_httpc:request_stream({self(), once}, get, RedirectUrl, IbrowseOpts);
post ->
- Body = ejson:encode({[{<<"keys">>, Args#view_query_args.keys}]}),
+ Body = couchbeam_ejson:encode({[{<<"keys">>, Args#view_query_args.keys}]}),
Headers = [{"Content-Type", "application/json"}],
couchbeam_httpc:request_stream({self(), once}, get, RedirectUrl,
IbrowseOpts, Headers, Body)

0 comments on commit d4574e4

Please sign in to comment.