2012-11-12 44 views
3

在JSON API中使用Erlang的最佳实践是什么? 我的意思是你如何处理JSON - 逻辑 - 数据库 - 逻辑 - JSON生命周期。您在Erlang应用程序中使用了哪些数据结构,工具和技术?Erlang JSON API数据生命周期

回答

7

有两个工具我倾向于在二郎用于JSON:jsxjiffy。检查它们,因为它们具有稍微不同的性质,灵活性和速度。

主要的问题是Erlang没有内置的字典类型。因此,JSON对象通常表示为属性列表,即

{ a : 10, 
    b : 20 } 

表示为元组的列表:

[{a, 10}, {b, 20}] 

,这是看出来了重大的事情。这也意味着应该尽可能地避免使用JSON作为内部表示格式,因为从长远来看,处理起来很不方便。

+2

另一种选择是'mochisjon2',它附带[Mochiweb](https://github.com/mochi/mochiweb)。 [Webmachine](https://github.com/basho/webmachine)基于Mochiweb。 – Tilman

+0

现在呢! Erlang 17 –

+0

@ArthurColléErlang 18,不,它没有,是的,它有地图,但它没有地图:to_json/1。 – Aus

5

为了使用JSON,我使用mochijson2和Erlson

mochijson2mochiweb项目的一部分。这是一个稳定的,经过战斗测试的纯Erlang实现,具有灵活的JSON解析和生成API。

Erlson为Erlang提供了一个很好的字典语法,在使用JSON时特别方便。例如:

#[ 
    foo = 1, 
    bar = "some string", 
    nested = #[i = 1, b = true] 
] 

此外,Erlson自带erlson:to_jsonerlson:from_json功能Erlson和JSON使用mochiweb2之间的转换。

(免责声明:我Erlson的作者)

1

你的问题比收到的答案为止更大。但是,对于操纵JSON,他们已经告诉了你关于mochijson.erl,mochijson2.erl所有这些都与mochiweb HTTP库一起提供的信息。要使用它们,一个JSON对象被表示为Struct对象是这样的:

 
In JSON
{"FirstName": "Joshua", "Surname": "Muzaaya"}
In Erlang
{struct,[{<<"FirstName">>,<<"Joshua">>},{<<"Surname">>,<<"Muzaaya">>}]}

解析来来回回:

 
JSON_DATA = {"students":[
{"student_number":45,
"details":[{"FirstName": "Joshua", "Surname": "Muzaaya"} ] } ]}
From JSON to Erlang
$> mochijson2:decode(JSON_DATA). {struct,[{<<"students">>, [{struct,[{<<"student_number">>,45}, {<<"details">>, [{struct,[{<<"FirstName">>,<<"Joshua">>}, {<<"Surname">>,<<"Muzaaya">>}]}]}]}]}]}
From Erlang to JSON
$> mochijson2:encode(StructObject).
现在的数据库,我不知道你真正想要的,但是,通常情况下,我们可以写数据在Key Value商店中, MnesiaCouchDB经由 RESTFUL访问API。我在Erlang写了一个 Couchbase Single Server客户端。这里有一些里面的功能:
 
create_database(ServerDomain,DBName)-> 
    try ibrowse:send_req(ServerDomain ++ DBName,[{"Content-Type",
"application/json"}],put,[]) of
{ok,_,_,Result} -> case proplists:get_value(<<"ok">>,element(2,mochijson2:decode(Result
))) of undefined -> {error,failed}; _ -> ok end; Any -> {error,Any} catch EE:EE2 -> {error,{EE,EE2}} end.
delete_database(ServerDomain,DBName)-> try ibrowse:send_req(ServerDomain ++ DBName,[{"Content-Type","application/json"}],delete,[]) of {ok,_,_,Result} -> case proplists:get_value(<<"ok">>,element(2,mochijson2:decode(Result))) of undefined -> {error,failed}; _ -> ok end; Any -> {error,Any} catch EE:EE2 -> {error,{EE,EE2}} end.
%% read/3 ::= Struct
read(ServerDomain,DBName,DocId)-> try ibrowse:send_req(ServerDomain ++ DBName ++ "/" ++ DocId,[{"Content-Type","application/json"}],get,[]) of
{ok,_,_,Result} -> mochijson2:decode(Result);
Any -> {error,Any} catch EE:EE2 -> {error,{EE,EE2}} end.

%% write/3 ::= [{id,Id::string()},{rev,Rev::string()}]
write(ServerDomain,DBName,DocStruct)-> try ibrowse:send_req(ServerDomain ++ DBName,[{"Content-Type","application/json"}],post,lists:flatten(mochijson:encode(DocStruct))) of
{ok,_,_,Result} -> E = element(2,mochijson2:decode(Result)), case {proplists:get_value(<<"id">>,E),proplists:get_value(<<"rev">>,E)} of {undefined,_} -> {error,E}; {_,undefined} -> {error,E}; {Id,Rev} -> [{id,binary_to_list(Id)},{rev,binary_to_list(Rev)}]
end;
Any -> {error,Any} catch EE:EE2 -> {error,{EE,EE2}} end.

%% remember to specify the '_rev' of recent copy when updating %% update/4 ::= [{id,Id::string()},{rev,Rev::string()}] update(ServerDomain,DBName,DocId,DocStruct)-> try ibrowse:send_req(ServerDomain ++ DBName ++ "/" ++ DocId,[{"Content-Type","application/json"}],put,lists:flatten(mochijson:encode(DocStruct))) of
{ok,_,_,Result} -> E = element(2,mochijson2:decode(Result)), case {proplists:get_value(<<"id">>,E),proplists:get_value(<<"rev">>,E)} of {undefined,_} -> {error,E}; {_,undefined} -> {error,E}; {Id,Rev} -> [{id,binary_to_list(Id)},{rev,binary_to_list(Rev)}]
end;
Any -> {error,Any} catch EE:EE2 -> {error,{EE,EE2}} end.

%% you need to provide the '_rev' of current copy %% of doc to be deleted
delete(ServerDomain,DBName,DocId,Rev)-> try ibrowse:send_req(ServerDomain ++ DBName ++ "/" ++ DocId ++ "?rev=" ++ Rev,[{"Content-Type","application/json"}],delete,[]) of
{ok,_,_,Result} -> E = element(2,mochijson2:decode(Result)), case {proplists:get_value(<<"id">>,E),proplists:get_value(<<"ok">>,E)} of {undefined,_} -> {error,E}; {_,undefined} -> {error,E}; {_Id,_} -> ok
end;
Any -> {error,Any} catch EE:EE2 -> {error,{EE,EE2}} end.

random(ServerDomain,Count) when is_integer(Count)-> try ibrowse:send_req(ServerDomain ++ "_uuids?count=" ++ integer_to_list(Count),[{"Content-Type","application/json"}],get,[]) of {ok,_,_,Result} -> [binary_to_list(Z) || Z <- proplists:get_value(<<"uuids">>,element(2,mochijson2:decode(Result)))]; Any -> {error,Any} catch EE:EE2 -> {error,{EE,EE2}} end.

所以,也许尝试打破你的问题。否则,你可以在上面看到我正在玩JSON。要使用abpve的方法,请先使用户ibrowse正在运行。