我刚刚开始修补Erlang并正在构建一个非常简单的测试网络应用程序,它只是为了显示我的推特时间线。
我正在使用webmachine编写应用程序,使用erlyDTL来渲染模板。
我的问题与mochiweb的mochijson2:decode/1
函数返回的结构有关。
我可以成功获取和取消时间轴,如下例所示:
1> Url = "http://api.twitter.com/1/statuses/user_timeline.json?screen_name=<TWITTER_SCREEN_NAME_HERE>".
2> inets:start().
3> {ok, {_, _, Response}} = httpc:request(Url).
4> DecodedJson = mochijson2:decode(Response).
mochijson2:decode/1
函数返回格式的元组列表:
[{struct, proplist()}, {struct, proplist()}, ...]
但是,要将时间轴传递给erlyDTL,我需要删除struct
atom标记,并简单地将一个proplists列表传递给webmachine资源(由erlyDTL呈现)。作为模式匹配的新手,我认为以下列表理解可以达到这个目的:
Timeline = [Tweet || {struct, Tweet} <- DecodedJson].
实际上,这适用于每个推文列表中的所有项目,除了一个<<"user">>
,其值本身一个{struct, proplist()}
元组。我不能为我的生活弄清楚如何从这个嵌套元组中查找struct
原子,并想知道是否有人可以提供一个Erlang代码示例,它将模式匹配{{1}中的外部推文每个推文中都包含用户{struct, Tweet}
。
最终目标是能够以Django模板语言访问每条推文,如下例所示:
{struct, User}
非常感谢任何帮助!
答案 0 :(得分:2)
以下是我们在内部用于类似目的的内容:
%% @doc Flatten {struct, [term()]} to [term()] recursively.
destruct({struct, L}) ->
destruct(L);
destruct([H | T]) ->
[destruct(H) | destruct(T)];
destruct({K, V}) ->
{K, destruct(V)};
destruct(Term) ->
Term.
对于mochijson2术语的其他用途,KVC可能对您有用:https://github.com/etrepum/kvc
答案 1 :(得分:2)
在我最近开展的一个项目中,我们正在处理来自 EXT JS 前端应用程序的大型JSON数据结构。下面是JSON对象的一个示例(这只是JSON的骨架):
{ "presence_token":"734737328233HDHSBSHSYEYEYWYWGWE", "presence_time":"HH:Mins:Secs", "friend_requests": [ { "from":"Username", "type":"buddy", "date":"DD/MM/YY", "time":"HH:Mins:Secs", "name":"Your Full name", "email":"user@example.com" } ], "group_status": [ { "group_name":"ecampus", "status":"running", "members":["phil","josh","shazz"], "start_date":"DD/MM/YY", "start_time":"HH:Mins:Secs" }, { "group_name":"buganda", "status":"off" } ], "friend_status": [ { "friend":"Friend_username", "status":"online", "log_on_time":"HH:Mins:Secs", "state":"available", "name":"Friend_Fullname", "email":"user@example.com" }, { "friend":"Friend_username", "status":"offline", "name":"Friend_Fullname", "email":"user@example.com" } ] }
在mochijson2:decode/1
之后,我看起来像这样的结构对象:
{struct,[{<<"presence_token">>, <<"734737328233HDHSBSHSYEYEYWYWGWE">>}, {<<"presence_time">>,<<"HH:Mins:Secs">>}, {<<"friend_requests">>, [{struct,[{<<"from">>,<<"Username">>}, {<<"type">>,<<"buddy">>}, {<<"date">>,<<"DD/MM/YY">>}, {<<"time">>,<<"HH:Mins:Secs">>}, {<<"name">>,<<"Your Full name">>}, {<<"email">>,<<"user@example.com">>}]}]}, {<<"group_status">>, [{struct,[{<<"group_name">>,<<"ecampus">>}, {<<"status">>,<<"running">>}, {<<"members">>,[<<"phil">>,<<"josh">>,<<"shazz">>]}, {<<"start_date">>,<<"DD/MM/YY">>}, {<<"start_time">>,<<"HH:Mins:Secs">>}]}, {struct,[{<<"group_name">>,<<"buganda">>}, {<<"status">>,<<"off">>}]}]}, {<<"friend_status">>, [{struct,[{<<"friend">>,<<"Friend_username">>}, {<<"status">>,<<"online">>}, {<<"log_on_time">>,<<"HH:Mins:Secs">>}, {<<"state">>,<<"available">>}, {<<"name">>,<<"Friend_Fullname">>}, {<<"email">>,<<"user@example.com">>}]}, {struct,[{<<"friend">>,<<"Friend_username">>}, {<<"status">>,<<"offline">>}, {<<"name">>,<<"Friend_Fullname">>}, {<<"email">>,<<"user@example.com">>}]}]}]}
现在我决定创建一个模块,将这个结构转换为&#34; deep&#34; proplist,这个模块将包含一个函数struct:all_keys/1
,如果我用struct对象提供它,它会以有条理的方式生成列表和元组。这是代码:
-module(struct). -export([all_keys/1]). is_struct({struct,_}) -> true; is_struct(_) -> false. to_binary(S) when is_list(S)-> list_to_binary(S); to_binary(S) when is_integer(S)-> S; to_binary(S) when is_atom(S)-> to_binary(atom_to_list(S)); to_binary(S) -> S. to_value(V) when is_binary(V)-> binary_to_list(V); to_value(V) when is_integer(V)-> V; to_value(V) when is_list(V)-> try list_to_integer(V) of PP -> PP catch _:_ -> try list_to_float(V) of PP2 -> PP2 catch _:_ -> V end end; to_value(A)-> A. to_value2({struct,L})-> all_keys({struct,L}); to_value2([{struct,_L}|_Rest] = LL)-> [all_keys(XX) || XX <- LL]; to_value2(D) when is_binary(D)-> to_value(D); to_value2(D) when is_list(D)-> [to_value2(Any) || Any <- D]. all_keys({struct,L})-> [{to_value(Key),to_value2(Val)} || {Key,Val} <- L]; all_keys(List)-> [all_keys(X) || X <- List].
现在,调用struct:all_keys(Struct_object)
将提供此输出:
[{"presence_token",P_token}, {"presence_time",P_time}, {"friend_requests", [[{"from","Username"}, {"type","buddy"}, {"date","DD/MM/YY"}, {"time","HH:Mins:Secs"}, {"name","Your Full name"}, {"email","user@example.com"}]]}, {"group_status", [[{"group_name","ecampus"}, {"status","running"}, {"members",["phil","josh","shazz"]}, {"start_date","DD/MM/YY"}, {"start_time","HH:Mins:Secs"}], [{"group_name","buganda"},{"status","off"}]]}, {"friend_status", [[{"friend","Friend_username"}, {"status","online"}, {"log_on_time","HH:Mins:Secs"}, {"state","available"}, {"name","Friend_Fullname"}, {"email","user@example.com"}], [{"friend","Friend_username"}, {"status","offline"}, {"name","Friend_Fullname"}, {"email","user@example.com"}]]}]
上述proplist比struct对象更容易使用。但是,你可能会发现另一个版本的struct模块,特别是在一个名为Sticky Notes的着名mochiweb示例中,我现在没有链接。我上面粘贴的struct模块应该可以帮助你使用mochijson2。 成功
答案 2 :(得分:0)
根据您描述的结构,您可以尝试:
timeline(List) -> timeline(List, []).
timeline([], Result) -> lists:reverse(Result);
timeline([{struct, S}|T], Result) -> timeline(T, [S|Result]);
timeline([{<<"user">>, {struct, S}}|T], Result) -> timeline(T, [S|Result]);
timeline([_|T], Result) -> timeline(T, Result).
我将该代码放在名为twitter
的模块中:
> twitter:timeline([{struct, 1}, {struct, 2}, {<<"user">>, {struct, 3}}, 5]).
[1,2,3]
您可能希望将<<"user">>
替换为_
,具体取决于您的具体需求。您可能还想介绍某种exception handling,因为您正在处理来自外部世界的输入。