简体   繁体   English

使用JSON的ERLANG

[英]ERLANG with JSON

I run following command in erlang , 我在erlang运行以下命令,

os:cmd("curl -k -X GET http://10.210.12.154:10065/iot/get/task").

It gives a JSON output like this, 它给出了这样的JSON输出,

{"data":[
    {"id":1,"task":"Turn on the bulb when the temperature in greater than 28","working_condition":1,"depending_value":"Temperature","action":"123"},
    {"id":2,"task":"Trun on the second bulb when the temperature is greater than 30","working_condition":0,"depending_value":"Temperature","action":"124"}
]}

I want to categorize this data to Id, task, depending_value, action. 我想将此数据分类为ID,任务,depending_value,操作。 It is like putting them in to a table. 就像将它们放在桌子上一样。 I want to easily find what is the depending value, working condition & action for Id=1. 我想轻松地找到Id = 1的相关值,工作条件和操作。 How can I do this? 我怎样才能做到这一点?

It gives a JSON output like this. 它给出了这样的JSON输出。

 {"data":[{"id":1,"t ... 

Highly doubtful. 高度怀疑。 The docs say that os:cmd() returns a string , which does not start with a { . 文档说os:cmd()返回的字符串不是以{开头。 Note also that a string is not even an erlang data type, rather double quotes are a shortcut for creating a list of integers , and a list of integers is not terribly useful in your case. 还要注意,字符串甚至都不是erlang数据类型,而双引号是创建list of integers捷径,并且整数列表在您的情况下并不是很有用。

Here are two options: 这里有两个选择:

  1. Call list_to_binary() on the list of integers returned by os:cmd() to covert to a binary . os:cmd()返回的整数列表上调用list_to_binary()list_to_binary()转换为binary

  2. Instead of os:cmd() , use an erlang http client, like hackney , which will return the json as a binary . 代替os:cmd() ,使用erlang http客户端(如hackney) ,它将以binary返回json。

The reason you want a binary is because then you can use an erlang json module, like jsx , to convert the binary into an erlang map (which might be what you are after?). 您想要二进制文件的原因是因为您可以使用jsx之类的erlang json模块将二进制文件转换为erlang映射(可能是您想要的?)。

Here's what that will look like: 如下所示:

3> Json = <<"{\"data\": [{\"x\": 1, \"y\": 2}, {\"a\": 3, \"b\": 4}] }">>. 
<<"{\"data\": [{\"x\": 1, \"y\": 2}, {\"a\": 3, \"b\": 4}] }">>

4> Map = jsx:decode(Json, [return_maps]).
#{<<"data">> =>
      [#{<<"x">> => 1,<<"y">> => 2},#{<<"a">> => 3,<<"b">> => 4}]}

5> Data = maps:get(<<"data">>, Map).     
[#{<<"x">> => 1,<<"y">> => 2},#{<<"a">> => 3,<<"b">> => 4}]

6> InnerMap1 = hd(Data).   
#{<<"x">> => 1,<<"y">> => 2}

7> maps:get(<<"x">>, InnerMap1).
1

...putting them in to a table. ...把他们放在桌子上。 I want to easily find what is the depending value, working condition & action for Id=1. 我想轻松地找到Id = 1的相关值,工作条件和操作。

Erlang has various table implementations: ets , dets , and mnesia . Erlang有各种表实现: etsdetsmnesia Here is an ets example: 这是一个ets示例:

-module(my).
-compile(export_all).

get_tasks() ->
    Method = get,

    %See description of this awesome website below.
    URL = <<"https://my-json-server.typicode.com/7stud/json_server/db">>,

    Headers = [],
    Payload = <<>>,
    Options = [],

    {ok, 200, _RespHeaders, ClientRef} =
        hackney:request(Method, URL, Headers, Payload, Options),
    {ok, Body} = hackney:body(ClientRef),
    %{ok, Body} = file:read_file('json/json.txt'),  %Or, for testing you can paste the json in a file (without the outer quotes), and read_file() will return a binary.

    Map = jsx:decode(Body, [return_maps]),
    _Tasks = maps:get(<<"data">>, Map).

create_table(TableName, Tuples) ->
    ets:new(TableName, [set, named_table]),
    insert(TableName, Tuples).

insert(_Table, []) ->
    ok;
insert(Table, [Tuple|Tuples]) ->
    #{<<"id">> := Id} = Tuple,
    ets:insert(Table, {Id, Tuple}),
    insert(Table, Tuples).

retrieve_task(TableName, Id) ->
    [{_Id, Task}] = ets:lookup(TableName, Id), 
    Task.

By default, an ets set type table ensures that the first position in the inserted tuple is the unique key (or you can explicitly specify another position in the tuple as the unique key). 默认情况下,ets set类型表确保插入的元组中的第一个位置是唯一键(或者您可以在元组中显式指定另一个位置作为唯一键)。

** If you have a github account, I discovered a really cool website that allows you to place a json file in a new repository on github, and the website will serve up that file as json. **如果您有github帐户,我发现了一个非常酷的网站,它允许您将json文件放置在github上的新存储库中,并且该网站会将该文件用作json。 Check it out at https://my-json-server.typicode.com : https://my-json-server.typicode.com上进行检查:

How to 如何

  1. Create a repository on GitHub (<your-username>/<your-repo>) 在GitHub上创建存储库(<your-username>/<your-repo>)的存储库(<your-username>/<your-repo>)
  2. Create a db.json file [in the repository]. 在存储库中创建一个db.json文件。
  3. Visit https://my-json-server.typicode.com/ <your-username>/<your-repo> to access your server 访问https://my-json-server.typicode.com/ <your-username>/<your-repo>以访问您的服务器

You can see the url I'm using in the code, which can be obtained by clicking on the link at the provided server page and copying the url in your web browser's address bar. 您可以在代码中看到我正在使用的url,可以通过单击提供的服务器页面上的链接并将该url复制到Web浏览器的地址栏中来获得。

In the shell: 在外壳中:

.../myapp$ rebar3 shell
===> Verifying dependencies...
===> Compiling myapp
src/my.erl:2: Warning: export_all flag enabled - all functions will be exported

Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [kernel-poll:false]
Eshell V9.3  (abort with ^G)

1> ===> The rebar3 shell is a development tool; to deploy applications in production, consider using releases (http://www.rebar3.org/docs/releases) 
===> Booted unicode_util_compat
===> Booted idna
===> Booted mimerl
===> Booted certifi
===> Booted ssl_verify_fun
===> Booted metrics
===> Booted hackney

1> Tasks = my:get_tasks().     
[#{<<"action">> => <<"123">>,
   <<"depending_value">> => <<"Temperature">>,<<"id">> => 1,
   <<"task">> =>
       <<"Turn on the bulb when the temperature in greater than 28">>,
   <<"working_condition">> => 1},
 #{<<"action">> => <<"124">>,
   <<"depending_value">> => <<"Temperature">>,<<"id">> => 2,
   <<"task">> =>
       <<"Trun on the second bulb when the temperature is greater than 30">>,
   <<"working_condition">> => 0}]

2> my:create_table(tasks, Tasks).
ok

3> my:retrieve_task(tasks, 1).   
#{<<"action">> => <<"123">>,
  <<"depending_value">> => <<"Temperature">>,<<"id">> => 1,
  <<"task">> =>
      <<"Turn on the bulb when the temperature in greater than 28">>,
  <<"working_condition">> => 1}

4> my:retrieve_task(tasks, 2).   
#{<<"action">> => <<"124">>,
  <<"depending_value">> => <<"Temperature">>,<<"id">> => 2,
  <<"task">> =>
      <<"Trun on the second bulb when the temperature is greater than 30">>,
  <<"working_condition">> => 0}

5> my:retrieve_task(tasks, 3).
** exception error: no match of right hand side value []
     in function  my:retrieve_task/2 (/Users/7stud/erlang_programs/old/myapp/src/my.erl, line 58)

6> 

Note that the id is over to the right at the end of one of the lines. 请注意,id在其中一行的末尾位于右侧。 Also, if you get any errors in the shell, the shell will automatically restart a new process and the ets table will be destroyed, so you have to create it anew. 另外,如果您在Shell中遇到任何错误,则Shell将自动重新启动新进程,并且ets表将被销毁,因此您必须重新创建它。

rebar.config: rebar.config:

{erl_opts, [debug_info]}.
{deps, [
    {jsx, "2.8.0"},
    {hackney, ".*", {git, "git://github.com/benoitc/hackney.git", {branch, "master"}}}
]}.
{shell, [{apps, [hackney]}]}. % This causes the shell to automatically start the listed apps.  See https://stackoverflow.com/questions/40211752/how-to-get-an-erlang-app-to-run-at-starting-rebar3/45361175#comment95565011_45361175

src/myapp.app.src: src / myapp.app.src:

{application, 'myapp',
 [{description, "An OTP application"},
  {vsn, "0.1.0"},
  {registered, []},
  {mod, {'myapp_app', []}},
  {applications,
   [kernel,
    stdlib
   ]},
  {env,[]},
  {modules, []},

  {contributors, []},
  {licenses, []},
  {links, []}
 ]}.

But, according to the rebar3 dependencies docs : 但是,根据rebar3依赖文档

You should add each dependency to your app or app.src files: 您应该将每个依赖项添加到您的app或app.src文件中:

So, I guess src/myapp.app.src should look like this: 因此,我猜src/myapp.app.src应该看起来像这样:

{application, 'myapp',
 [{description, "An OTP application"},
  {vsn, "0.1.0"},
  {registered, []},
  {mod, {'myapp_app', []}},
  {applications,
   [kernel,
    stdlib,
    jsx,
    hackney
   ]},
  {env,[]},
  {modules, []},

  {contributors, []},
  {licenses, []},
  {links, []}
 ]}.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM