2011-06-10 44 views
1

我刚刚开始修改Erlang,并且正在构建一个非常简单的测试Web应用程序,该应用程序仅用于显示我的Twitter时间表。如何模式mochijson2返回的匹配结构?

我正在使用webmachine编写app和erlyDTL来呈现模板。

我的问题与mochiweb的mochijson2:decode/1函数返回的结构有关。

我能成功抓取和deocde我的时间表,如下面的例子:

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()}, ...] 

然而,通过时间轴into erlyDTL我需要摆脱struct原子标记,并简单地将一列proplists传递给webmachine资源(由erlyDTL呈现)。作为很新的模式匹配,我盘算了一下,下面的列表理解将实现这一点:

Timeline = [Tweet || {struct, Tweet} <- DecodedJson]. 

事实上,这完全适用于所有在每次发推proplist这样的项目除了一个,<<"user">>,其值是本身 a {struct, proplist()}元组。我无法想象如何从这个嵌套元组中剔除struct原子,并想知道是否有人可以提供一个Erlang代码示例,它将模式匹配{struct, Tweet}中的外部Tweet和每个中包含的用户{struct, User}鸣叫。

的最终目标是要能够访问每个鸣叫在Django模板语言如下面的例子:

{{ tweet.text }} <- works 
{{ tweet.created_at }} <- works 
{{ tweet.user.profile_image_url }} <- ??? 

任何帮助将不胜感激!

+0

你能发布一个实际的例子时间表,显示你的问题? – DefLog 2011-06-10 18:20:20

回答

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,因为您正在处理来自外部世界的输入。

+0

感谢大卫 - 因为我对Erlang非常陌生,所以随着我的发展,我会将异常处理迭代到应用程序中。现在,我仍然习惯于不去思考Python范例:-) – peeb 2011-06-12 10:28:39

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

+0

我把它作为helpers推入模块:destruct(),它完美地工作。真棒。非常感谢 - 也为KVC提示。 – peeb 2011-06-12 10:27:05

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":"[email protected]" 
      } 
     ], 
     "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":"[email protected]"    
      }, 
      { 
       "friend":"Friend_username", 
       "status":"offline",     
       "name":"Friend_Fullname", 
       "email":"[email protected]"    
      }   
     ]   
    } 

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">>,<<"[email protected]">>}]}]}, 
       {<<"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">>,<<"[email protected]">>}]}, 
        {struct,[{<<"friend">>,<<"Friend_username">>}, 
          {<<"status">>,<<"offline">>}, 
          {<<"name">>,<<"Friend_Fullname">>}, 
          {<<"email">>,<<"[email protected]">>}]}]}]} 

现在我决定创建一个模块将这个结构转换为一个“深”的proplist,这个模块将包含一个函数struct:all_keys/1,如果我给它提供结构对象,它会以有组织的方式生成列表和元组。下面是代码:

 
-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","[email protected]"}]]}, 
{"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","[email protected]"}], 
    [{"friend","Friend_username"}, 
    {"status","offline"}, 
    {"name","Friend_Fullname"}, 
    {"email","[email protected]"}]]}] 

以上proplist这样更容易与工作比结构对象。但是,您可能会发现另一个版本的结构模块,特别是在着名的mochiweb示例中,这个示例名为粘滞便笺,其链接我现在没有。上面粘贴的结构模块应该能够帮助您使用mochijson2。 成功

+1

我试图使用你的代码,并发现一个错误。在“{”from“,”Username“}之前有两个”[[“),但代码对于进一步修改非常有帮助。 – 2012-03-19 13:13:29