erlang JSON 数据 - 如何 select 只有一个值

erlang JSON data - how to select only one value

在 erlang 语言中,我收到了 JSON 数据的孩子:

{"Time":"2020-08-16T15:28:55","BME680":{"Temperature":29.8,"Humidity":55.5,"Pressure":1003.5,"Gas":422.24},"PressureUnit":"hPa","TempUnit":"C"}

{"Time":"2020-08-16T11:39:49","SI7021":{"Temperature":32.4,"Humidity":99.9},"TempUnit":"C"}

我需要 select 每个 JSON 数据只有一个值,例如: 基于“BME680”值

{"Temperature":29.8,"Humidity":54.8,"Pressure":1005.0,"Gas":1513.60}

或 基于“SI7021”值

{"Temperature":32.4,"Humidity":99.9}

如何用 erlang 语言激活这个任务? 如果它更简单,我需要提取每个 JSON 数据的第二个值。

为了将JSON格式解码成Erlang格式的数据,如proplists or into the maps, you can try to use 3rd party library jiffy,那么可以使用简单的模式匹配,例如:

地图:

1> JSON = "{\"Time\":\"2020-08-17T05:32:09\",\"BME680\":{\"Temperature\":29.6,\"Humidity\":54.6,\"Pressure\":1003.9,\"Gas\":1517.91},\"PressureUnit\":\"hPa\",\"TempUnit\":\"C\"}".
2> Map = jiffy:decode(JSON,[return_maps]).
3> #{<<"BME680">> := BME680} = Map.
4> BME680.
#{<<"Gas">> => 1517.91,<<"Humidity">> => 54.6, <<"Pressure">> => 1003.9,<<"Temperature">> => 29.6}

支持者:

1> JSON = "{\"Time\":\"2020-08-17T05:32:09\",\"BME680\":{\"Temperature\":29.6,\"Humidity\":54.6,\"Pressure\":1003.9,\"Gas\":1517.91},\"PressureUnit\":\"hPa\",\"TempUnit\":\"C\"}".
2> {Proplists} = jiffy:decode(JSON).
3> [BME680] = [V || {K, V} <- Proplists, K == <<"BME680">>].
4> BME680.
{[{<<"Temperature">>,29.6},{<<"Humidity">>,54.6},{<<"Pressure">>,1003.9},{<<"Gas">>,1517.91}]}

您需要熟悉 rebar3, which is erlang's package manager. Then, you can use a package like jsx,这将允许您在二进制类型和映射之间进行转换。首先,您需要将调用“JSON”的任何内容转换为二进制类型,也许使用 tuple_to_list() 然后 list_to_binary(),然后您可以使用 jsx 包转换二进制到地图,这将使您能够从地图中提取目标值。

这是一个例子:

my.erl:

json_to_map(Bin) ->
    jsx:decode(
      %%<<"{\"data\": [1, 2, 3]}">>,
      Bin,
      [return_maps]
    ).

在shell中:

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

~/erlang_programs/myapp$ rebar3 shell
===> Verifying dependencies...
===> Compiling myapp
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> Bin1 = <<"{\"A\": 100, \"B\":{\"x\": 4,\"y\": [1,2,3]}}">>.
<<"{\"A\": 100, \"B\":{\"x\": 4,\"y\": [1,2,3]}}">>

2> Bin2 = <<"{\"A\":200, \"C\":{\"a\": 6, \"b\": [3,4,5]}}">>.
<<"{\"A\":200, \"C\":{\"a\": 6, \"b\": [3,4,5]}}">>

3> M1 = my:json_to_map(Bin1).                                 
#{<<"A">> => 100,
  <<"B">> => #{<<"x">> => 4,<<"y">> => [1,2,3]}}

4> M2 = my:json_to_map(Bin2).                                 
#{<<"A">> => 200,
  <<"C">> => #{<<"a">> => 6,<<"b">> => [3,4,5]}}


5> [V1] = maps:values( maps:without([<<"A">>], M1)).
[#{<<"x">> => 4,<<"y">> => [1,2,3]}]

6> V1.
#{<<"x">> => 4,<<"y">> => [1,2,3]}

7> [V2] = maps:values( maps:without([<<"A">>], M2)).
[#{<<"a">> => 6,<<"b">> => [3,4,5]}]

8> V2.
#{<<"a">> => 6,<<"b">> => [3,4,5]}

9> 

您好,如果“Body”等于:

    "{\"Time\":\"2020-08-17T05:32:09\",\"BME680\":{\"Temperature\":29.6,\"Humidity\":54.6,\"Pressure\":1003.9,\"Gas\":1517.91},\"PressureUnit\":\"hPa\",\"TempUnit\":\"C\"}"

我的代码

     ....
     eBody = jiffy:decode(<<Body>>),
     Map = #eBody,
     #{"BME680" := BME680} = Map,
     newbody = jiffy:encode(BME680),
     HTTPOptions = [],
     Options = [],
     R = httpc:request(Method, {URL, Header, Type, newbody},HTTPOptions, Options),
     ....

我是 erlang 的新手。

您可以使用 mochiweb 项目中的 2 个模块:

  1. https://github.com/mochi/mochiweb/blob/master/src/mochijson2.erl
  2. https://raw.githubusercontent.com/mochi/mochiweb/master/src/mochinum.erl

将它们放在某个文件夹中 (f.e.test) 和 运行 erl shell 并编译这些文件:

alexei@MacBook-Pro test % erl
Erlang/OTP 23 [erts-11.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]

Eshell V11.0  (abort with ^G)
1> c("mochijson2.erl").
{ok,mochijson2}

2> c("mochinum.erl").
{ok,mochinum}

将json-as-text解码为json-as-erlang-term:

3> Body = "{\"Time\":\"2020-08-16T15:28:55\",\"BME680\":{\"Temperature\":29.8,\"Humidity\":55.5,\"Pressure\":1003.5,\"Gas\":422.24},\"PressureUnit\":\"hPa\",\"TempUnit\":\"C\"}".
"{\"Time\":\"2020-08-16T15:28:55\",\"BME680\":{\"Temperature\":29.8,\"Humidity\":55.5,\"Pressure\":1003.5,\"Gas\":422.24},\"PressureUnit\":\"hPa\",\"TempUnit\":\"C\"}"

4> {struct, Map} = mochijson2:decode(Body).
{struct,[{<<"Time">>,<<"2020-08-16T15:28:55">>},
         {<<"BME680">>,
          {struct,[{<<"Temperature">>,29.8},
                   {<<"Humidity">>,55.5},
                   {<<"Pressure">>,1003.5},
                   {<<"Gas">>,422.24}]}},
         {<<"PressureUnit">>,<<"hPa">>},
         {<<"TempUnit">>,<<"C">>}]}

检索您需要的项目:

5> {struct, Obj1} = proplists:get_value(<<"BME680">>, Map).
{struct,[{<<"Temperature">>,29.8},
         {<<"Humidity">>,55.5},
         {<<"Pressure">>,1003.5},
         {<<"Gas">>,422.24}]}

6> Item1 = proplists:lookup(<<"Temperature">>, Obj1).  
{<<"Temperature">>,29.8}

7> Item2 = proplists:lookup(<<"Humidity">>, Obj1).   
{<<"Humidity">>,55.5}

并将 erlang 术语编码为文本:

8> List = [Item1, Item2].
[{<<"Temperature">>,29.8},{<<"Humidity">>,55.5}]

9> iolist_to_binary(mochijson2:encode({struct, List})).
<<"{\"Temperature\":29.8,\"Humidity\":55.5}">>

mochijson2 的文档非常简短,但在 shell 中练习很容易学习。