ЭРЛАНГ с JSON

Я запускаю следующую команду в erlang,

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

Он дает такой вывод 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"}
]}

Я хочу классифицировать эти данные по идентификатору, задаче, зависимости_значения, действию. Это как положить их на стол. Я хочу легко найти зависимое значение, рабочее состояние и действие для Id = 1. Как я могу это сделать?

{\"статус\":200,\"данные\":[{\"id\":1,\"задача\":\"Включить лампочку, когда температура выше 28\",\"working_condition \":1,\"depending_value\":\"Temperatu‌​re\",\"action\":\"12‌​3\"},{\"id\":2,\"tas‌​k\" :\"Включить вторую лампочку, когда температура выше 30\",\"рабочее_условие\":0,\"зависящее_значение\":\"Температура‌​re\",\"действие\":\"12‌​ 4\"}]}"

Chathura Jayawardane 25.01.2019 10:59

Вы пытались использовать одну из библиотек разбора JSON, например jsx? Попробуйте это и опубликуйте код, который вы сделали, и тогда вы сможете получить более конкретную помощь.

Máté 25.01.2019 11:20

Я пробовал с rfc4627. Это код.

Chathura Jayawardane 25.01.2019 11:27

-модуль(задачи). -экспорт([run_forever/0]). run_forever() -> Arg = os:cmd("curl -k -X GET 10.210.12.154:10065/iot/получить/задача"), io:fwrite("~p~n",[Arg]), case decode_json(Arg) of {ok, Data} -> case catch rfc4627:get_field(данные, "id") из {ok, Id} -> case catch rfc4627:get_field(данные, "working_condition") из {ok, Wc} -> io:fwrite("~p~n" ,[Wc]), конец конец; run_forever().

Chathura Jayawardane 25.01.2019 11:33
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
1
4
1 127
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

It gives a JSON output like this.

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

Весьма сомнительно. В документации сказано, что ОС: cmd() возвращает строка, который не начинается с {. Также обратите внимание, что строка — это даже не тип данных erlang, а двойные кавычки — это ярлык для создания list of integers, а список целых чисел в вашем случае не очень полезен.

Вот два варианта:

  1. Вызовите list_to_binary() из списка целых чисел, возвращаемых os:cmd(), чтобы преобразовать его в binary.

  2. Вместо os:cmd() используйте http-клиент erlang, например хакни, который вернет json как binary.

Причина, по которой вам нужен двоичный файл, заключается в том, что тогда вы можете использовать модуль json erlang, например jsx, для преобразования двоичного файла в карту erlang (что может быть тем, что вам нужно?).

Вот как это будет выглядеть:

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.

В Erlang есть различные реализации таблиц: ets, dets и mnesia. Вот пример 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.

По умолчанию таблица типа ets set гарантирует, что первая позиция во вставляемом кортеже является уникальным ключом (или вы можете явно указать другую позицию в кортеже в качестве уникального ключа).

** Если у вас есть учетная запись github, я обнаружил действительно классный веб-сайт, который позволяет вам поместить файл json в новый репозиторий на github, и веб-сайт будет обслуживать этот файл как json. Проверьте это на https://my-json-server.typicode.com:

How to

  1. Create a repository on GitHub (<your-username>/<your-repo>)
  2. Create a db.json file [in the repository].
  3. Visit https://my-json-server.typicode.com/<your-username>/<your-repo> to access your server

Вы можете увидеть URL-адрес, который я использую в коде, который можно получить, щелкнув ссылку на предоставленной странице сервера и скопировав URL-адрес в адресную строку вашего веб-браузера.

В оболочке:

.../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> 

Обратите внимание, что идентификатор находится справа в конце одной из строк. Кроме того, если вы получите какие-либо ошибки в оболочке, оболочка автоматически перезапустит новый процесс, и таблица ets будет уничтожена, поэтому вам придется создавать ее заново.

арматура.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

источник/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, []}
 ]}.

Но, согласно документация по зависимостям rebar3:

You should add each dependency to your app or app.src files:

Итак, я думаю, что 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, []}
 ]}.

Строка, указанная в вопросе, имеет формат JSON и, конечно же, не кортеж Erlang. В нем есть двоеточия, разделяющие имена свойств и значения — в Erlang такого нет.

Wojtek Surowka 26.01.2019 05:39

Я думаю, очевидно, что OP включал содержание строки, возвращаемой os:cmd. Ничего "весьма сомнительного" в этом нет.

Wojtek Surowka 26.01.2019 07:34

ТЕПЕРЬ ВЫВОД ТАКОЙ... ЧТО Я МОГУ СДЕЛАТЬ ДЛЯ ДАЛЬШЕ....... {\"статус\":200,\"данные\":[{\"id\":1,\"задача \":\"Включить лампочку, когда температура выше 28\",\"рабочее_условие\":1,\"зависящее_значение\":\"Температура‌​re\",\"действие\":\"12‌ ​3\"},{\"id\":2,\"tas‌​k\":\"Включить вторую лампочку, когда температура выше 30\",\"working_condition\":0,\" depend_value\":\"Температура\",\"действие\":\"12‌​4\"}]}"

Chathura Jayawardane 28.01.2019 05:56

Я хочу написать только один файл для выполнения этой работы. Возможно ли это?

Chathura Jayawardane 28.01.2019 06:04

@ChathuraJayawardane, я так не думаю. Вы должны научиться использовать rebar3, чтобы использовать сторонние приложения erlang, такие как hackney и jsx. Смотрите самый простой способ здесь: stackoverflow.com/questions/34278982/…

7stud 29.01.2019 05:24

Другие вопросы по теме