1

我刚刚开始修改 Erlang,并且正在构建一个非常简单的测试 Web 应用程序,它只是为了显示我的 Twitter 时间线。

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

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

我可以成功地获取和解码我的时间线,如下例所示:

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,我需要去掉structatom 标签,只需将 proplist 列表传递给 webmachine 资源(由 erlyDTL 呈现)。作为模式匹配的新手,我认为以下列表理解可以实现这一点:

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

实际上,这对于每个 Tweet proplist 中的所有项目都非常有效,除了一个,<<"user">>,其值本身就是一个{struct, proplist()}元组。我一生无法弄清楚如何struct从这个嵌套的元组中删除原子,并且想知道是否有人可以提供一个 Erlang 代码示例,该示例将模式匹配外部 Tweet和每个 Tweet 中包含{struct, Tweet}的用户。{struct, User}

最终目标是能够访问 Django 模板语言中的每条推文,如下例所示:

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

任何帮助将不胜感激!

4

3 回答 3

2

在我最近参与的一个项目中,我们正在处理来自EXT JS前端应用程序的大型 JSON 数据结构。下面是 JSON 对象的一个​​示例(这只是 JSON 的骨架):

{
        "presence_token":"734737328233HDHSBSHSYEYWYWGWE",
        "presence_time":"HH:Mins:Secs",
        “朋友请求”:
        [
            {
                "来自":"用户名",
                “类型”:“伙伴”,
                "日期":"DD/MM/YY",
                “时间”:“HH:分钟:秒”,
                "name":"你的全名",
                “电子邮件”:“用户@example.com”
            }
        ],
        “组状态”:
        [
            {
                "group_name":"ecampus",
                “状态”:“正在运行”,
                “成员”:[“菲尔”,“乔希”,“沙兹”],
                "start_date":"DD/MM/YY",
                "start_time":"HH:Mins:Secs"             
            },
            {
                "group_name":"buganda",
                “状态”:“关闭”
            }
        ],
        “朋友状态”:
        [
            {
                "friend":"朋友_用户名",
                “状态”:“在线”,
                "log_on_time":"HH:Mins:Secs",
                “状态”:“可用”,
                "name":"Friend_Fullname",
                “电子邮件”:“用户@example.com”              
            },
            {
                "friend":"朋友_用户名",
                “状态”:“离线”,                 
                "name":"Friend_Fullname",
                “电子邮件”:“用户@example.com”              
            }           
        ]           
    }

之后mochijson2:decode/1,我拥有的结构对象如下所示:

        {struct,[{<<"presence_token">>,
                  <<"734737328233HDHSBSHSYEYWYWGWE">>},
                 {<<"presence_time">>,<<"HH:Mins:Secs">>},
                 {<<"friend_requests">>,
                  [{struct,[{<<"来自">>,<<"用户名">>},
                            {<<"类型">>,<<"好友">>},
                            {<<"日期">>,<<"DD/MM/YY">>},
                            {<<"时间">>,<<"HH:Mins:Secs">>},
                            {<<"姓名">>,<<"你的全名">>},
                            {<<"email">>,<<"user@example.com">>}]}]},
                 {<<"组状态">>,
                  [{struct,[{<<"group_name">>,<<"ecampus">>},
                            {<<"状态">>,<<"运行">>},
                            {<<"members">>,[<<"phil">>,<<"josh">>,<<"shazz">>]},
                            {<<"开始日期">>,<<"DD/MM/YY">>},
                            {<<"start_time">>,<<"HH:Mins:Secs">>}]},
                   {struct,[{<<"group_name">>,<<"buganda">>},
                            {<<"状态">>,<<"关闭">>}]}]},
                 {<<"friend_status">>,
                  [{struct,[{<<"friend">>,<<"Friend_username">>},
                            {<<"状态">>,<<"在线">>},
                            {<<"log_on_time">>,<<"HH:Mins:Secs">>},
                            {<<"状态">>,<<"可用">>},
                            {<<"name">>,<<"Friend_Fullname">>},
                            {<<"email">>,<<"user@example.com">>}]},
                   {struct,[{<<"friend">>,<<"Friend_username">>},
                            {<<"状态">>,<<"离线">>},
                            {<<"name">>,<<"Friend_Fullname">>},
                            {<<"email">>,<<"user@example.com">>}]}]}]}

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

-模块(结构)。
-export([all_keys/1])。

is_struct({struct,_}) -> 真;
is_struct(_) -> 错误。

to_binary(S) 当 is_list(S)-> list_to_binary(S);
to_binary(S) 当 is_integer(S)-> S;
to_binary(S) 当 is_atom(S)-> to_binary(atom_to_list(S));
to_binary(S) -> S。

to_value(V) 当 is_binary(V)-> binary_to_list(V);
to_value(V) 当 is_integer(V)-> V;
to_value(V) when is_list(V)->
    尝试 list_to_integer(V) 的
        聚丙烯 -> 聚丙烯
    抓住
        _:_ ->
            尝试 list_to_float(V) 的
                PP2 -> PP2
            抓住
                _:_ -> V
            结尾
    结尾;
to_value(A)-> A。

to_value2({struct,L})->
    all_keys({struct,L});
to_value2([{struct,_L}|_Rest] = LL)->
    [所有键(XX)|| XX <- LL];
to_value2(D) 当 is_binary(D)-> to_value(D);
to_value2(D) 当 is_list(D)->
    [to_value2(任意) || 任何 <- D]。    

all_keys({struct,L})->
    [{to_value(Key),to_value2(Val)} || {键,值} <- L];
all_keys(列表)-> [all_keys(X) || X <- 列表]。

现在,调用struct:all_keys(Struct_object)将给出以下输出:

[{"presence_token",P_token},
 {"presence_time",P_time},
 {"friend_requests",
  [[{"来自","用户名"},
    {“类型”,“好友”},
    {"日期","DD/MM/YY"},
    {"time","HH:Mins:Secs"},
    {"name","你的全名"},
    {"email","user@example.com"}]]},
 {“组状态”,
  [[{"group_name","ecampus"},
    {"状态","运行"},
    {“成员”,[“菲尔”,“乔希”,“沙兹”]},
    {"start_date","DD/MM/YY"},
    {"start_time","HH:Mins:Secs"}],
   [{"group_name","buganda"},{"status","off"}]]},
 {“朋友状态”,
  [[{"friend","Friend_username"},
    {"状态","在线"},
    {"log_on_time","HH:Mins:Secs"},
    {“状态”,“可用”},
    {"name","Friend_Fullname"},
    {"email","user@example.com"}],
   [{"friend","Friend_username"},
    {"状态","离线"},
    {"name","Friend_Fullname"},
    {"email","user@example.com"}]]}]

上面的 proplist 比 struct 对象更容易使用。但是,您可能会发现 struct 模块的另一个版本,特别是在一个名为 Sticky Notes 的著名 mochiweb 示例中,我现在没有它的链接。我在上面粘贴的 struct 模块应该能够帮助您使用 mochijson2。成功

于 2011-06-13T08:34:33.287 回答
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

于 2011-06-11T17:29:32.623 回答
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">>替换。_您可能还想引入某种异常处理,因为您正在处理来自外部世界的输入。

于 2011-06-10T21:56:58.210 回答