ERLANG的这种格式是什么。看起来不像JSON?

时间:2018-02-20 11:55:53

标签: erlang mqtt erlang-shell

我刚使用file:write转储此变量:

file:write_file("/tmp/foo.txt", io_lib:fwrite("~p.\n", [Message])),

这是emqtt中插件代码的一部分。 我想解析这个内容,并在一个名为topic的变量中将消息变量和home / garden / fountain中的部分sdfjksdf。这该怎么做。我不知道二郎。

{mqtt_message,<<0,5,101,163,106,150,123,212,110,126,0,0,76,244,0,3>>,
              undefined,
              {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
              <<"home/garden/fountain">>,0,[],false,false,false,[],
              <<"sdfjksdf">>,
              {1519,127425,874902}}

这是我遇到问题的功能

on_message_publish(Message, _Env) ->
    io:format("publish ~s~n", [emqttd_message:format(Message)]),
    file:write_file("/tmp/foo.txt", io_lib:fwrite("~p.\n", [Message])),
    inets:start(),
    Method = post,
    URL = "http://xyz.in/api/v2/mysql/_table/device",
    Header = [{"Api-Key", "1234"}],
    Type = "application/json",
    Body = "{\"resource\":[{\"deviceid\":\"" ++ "msg" ++ "\"}]}",
    HTTPOptions = [],
    Options = [],
    R = httpc:request(Method, {URL, Header, Type, Body}, HTTPOptions, Options),
    {ok, Message}.

在上面的代码中,我必须传递字符串&#34; sdfjksdf&#34;来自Message对象并代替&#34; msg&#34;串。 我试过++ element(12,Message)++但它不起作用。

然后我尝试了++ binary_to_list(element(12,Message))++这也不起作用。

我如何传递字符串&#34; sdfjksdf&#34;来自Message对象通过连接传递给JSON字符串中作为参数的函数。

2 个答案:

答案 0 :(得分:3)

这是二郎中的一个元组。见:http://erlang.org/doc/reference_manual/data_types.html。这是元组在一个单独的行上组织的元组:

{
    mqtt_message,
    <<0,5,101,163,106,150,123,212,110,126,0,0,76,244,0,3>>,
    undefined,
    {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
    <<"home/garden/fountain">>,
    0,
    [],
    false,
    false,
    false,
    [],
    <<"sdfjksdf">>,
    {1519,127425,874902}
}

元组中第一个元素的索引是1.所以你可以这样做:

8> Data = f:get_data().
{mqtt_message,<<0,5,101,163,106,150,123,212,110,126,0,0,
                76,244,0,3>>,
              undefined,
              {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
              <<"home/garden/fountain">>,0,[],false,false,false,[],
              <<"sdfjksdf">>,
              {1519,127425,874902}}

9> Message = element(12, Data).
<<"sdfjksdf">>

10> Topic = element(5, Data).
<<"home/garden/fountain">>

对评论的回应:

  

还可以告诉你&lt;&lt;&gt;&gt;的含义是什么?上面的符号   元组

如果您在上面发布的链接中搜索了所有erlang数据类型的链接,那么您会发现这样的元素:

<<"sdfjksdf">>

称为二进制。二进制文件就像字符串一样,但对于二进制文件,erlang提供了一种语法,允许您将二进制文件切割成您想要的任何大小的块。这对于读取通过网络发送的字符串非常有用,前4位可以表示整个消息的长度,接下来的12位代表一些信息,接下来的3位代表其他一些信息等。

但是因为二进制文件也比字符串更有效,即使你不需要将字符串分割成其组成位,你也可以将字符串转换为二进制文件并传递它们。 erlang中的所有I / O工具都可以比字符串更有效地处理二进制文件。

但是,如果由于某种原因需要将二进制文件作为字符串,则可以使用函数binary_to_list()将二进制文件转换为字符串。在erlang中,字符串实际上是 list ,其中包含整数字符代码:

9> [97,98,99].
"abc"

...因此名称为binary_to_list。

以下是将二进制文件转换为字符串的示例:

7> TopicBin = <<"home/garden/fountain">>.
<<"home/garden/fountain">>

8> TopicStr = binary_to_list(TopicBin).
"home/garden/fountain"
9> 

回复编辑:

  

我试过++ element(12,Message) ++但它不起作用。

我们已经确定element(12, Message)的返回值是二进制值,但您应该检查以确保:

X = element(12, Message),
io:format("What is this: ~w~n", [X])

接下来,++运算符是string:concat()的快捷方式,它需要字符串参数,因此您不能将++与二进制文件一起使用。

  

然后我尝试++ binary_to_list(element(12,Message)) ++这也不起作用。

这有效:

2> Msg = "sdfjksdf".
"sdfjksdf"

3> Result = "hello " ++ Msg ++ " world".
"hello sdfjksdf world"

之前,我们讨论过如何将二进制文件转换为字符串(列表)。所以,你可以这样做:

5> Bin = <<"sdfjksdf">>.
<<"sdfjksdf">>

6> Msg = binary_to_list(Bin).   
"sdfjksdf"

7> "hello " ++ Msg ++ " world".

而且,最后一行相当于:

8> "hello " ++ binary_to_list(Bin) ++ " world".
"hello sdfjksdf world"

这里面是你的功能:

-module(f).
-compile(export_all).

get_message() ->
{
    mqtt_message,
    <<0,5,101,163,106,150,123,212,110,126,0,0,76,244,0,3>>,
    undefined,
    {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
    <<"home/garden/fountain">>,
    0,
    [],
    false,
    false,
    false,
    [],
    <<"sdfjksdf">>,
    {1519,127425,874902}
}.


on_message_publish(Message, _Env) ->
    %io:format("publish ~s~n", [emqttd_message:format(Message)]),
    %file:write_file("/tmp/foo.txt", io_lib:fwrite("~p.\n", [Message])),
    %inets:start(),
    DeviceIdBin = element(12, Message),
    DeviceIdStr = binary_to_list(DeviceIdBin),

    Method = post,
    URL = "http://xyz.in/api/v2/mysql/_table/device",
    Header = [{"Api-Key", "1234"}],
    Type = "application/json",
    Body = "{\"resource\":[{\"deviceid\":\"" ++ DeviceIdStr ++ "\"}]}",
    io:format("Body=~s~n", [Body]),
    %HTTPOptions = [],
    %Options = [],
    %R = httpc:request(Method, {URL, Header, Type, Body}, HTTPOptions, Options),
    {ok, Message}.


go() ->
    Message = get_message(),
    on_message_publish(Message, "hello").

在erlang shell中:

5> c(f).  
f.erl:29: Warning: variable 'Method' is unused
f.erl:30: Warning: variable 'URL' is unused
f.erl:31: Warning: variable 'Header' is unused
f.erl:32: Warning: variable 'Type' is unused
{ok,f}

6> f:go().
Body={"resource":[{"deviceid":"sdfjksdf"}]}
{ok,{mqtt_message,<<0,5,101,163,106,150,123,212,110,126,0,
                    0,76,244,0,3>>,
                  undefined,
                  {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
                  <<"home/garden/fountain">>,0,[],false,false,false,[],
                  <<"sdfjksdf">>,
                  {1519,127425,874902}}}
7> 

答案 1 :(得分:0)

该类型称为tuple,是一种Erlang数据类型。您通常可以将其视为固定长度的数组。 Erlang元组是1索引的。有几种方法可以从元组中提取数据。如果您知道元组的大小,例如:

{_,_,_,_,Message,_,_,_,_,_,_,Topic,_} = {mqtt_message,<<0,5,101,163,106,150,123,212,110,126,0,0,76,244,0,3>>,
              undefined,
              {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
              <<"home/garden/fountain">>,0,[],false,false,false,[],
              <<"sdfjksdf">>,
              {1519,127425,874902}}.

这将分别将您想要的数据绑定到Message和Topic变量。或者使用内置函数element

element(5, {mqtt_message,<<0,5,101,163,106,150,123,212,110,126,0,0,76,244,0,3>>,
              undefined,
              {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
              <<"home/garden/fountain">>,0,[],false,false,false,[],
              <<"sdfjksdf">>,
              {1519,127425,874902}}) 

或:

element(12, {mqtt_message,<<0,5,101,163,106,150,123,212,110,126,0,0,76,244,0,3>>,
              undefined,
              {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
              <<"home/garden/fountain">>,0,[],false,false,false,[],
              <<"sdfjksdf">>,
              {1519,127425,874902}})

我希望这能回答你的问题,干杯!

编辑: <<>>是一个Erlang二进制文件,这是一个非常大的主题。您可以阅读有关数据类型和内置二进制操作here的信息。

EDIT2: 我不完全确定你对原帖的最后编辑是什么意思。但是,如果您只想提取二进制文件<<"sdfjksdf">>并将其附加到现有字符串:

42> Msg = binary:bin_to_list(element(12,Message)).
"sdfjksdf"
43> "test: " ++ Msg.
"test: sdfjksdf"

您需要找出使用该语法将其附加到JSON正文中的正确方法。请记住,++操作对大型列表无效。