Erlang JSON数据-如何只选择一个值

bksxznpy  于 2022-12-08  发布在  Erlang
关注(0)|答案(4)|浏览(157)

在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"}

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

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

或基于“SI7021”值

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

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

vltsax25

vltsax251#

要将JSON格式的数据解码为Erlang格式(如proplistsmaps),您可以尝试使用第三方库jiffy,然后可以使用简单的模式匹配,例如:
Map:

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}]}
5us2dqdw

5us2dqdw2#

You can use 2 modules from mochiweb project:

  1. https://github.com/mochi/mochiweb/blob/master/src/mochijson2.erl
  2. https://raw.githubusercontent.com/mochi/mochiweb/master/src/mochinum.erl
    Put them in some folder (f.e. test) and run erl shell and compile this files:
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}

Decode json-as-text to 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">>}]}

Retrive the items you need:

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}

And encode erlang term to text:

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

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

There is a very short documentation for mochijson2, but it is easy to learn just practice in shell.

gkl3eglg

gkl3eglg3#

您需要熟悉rebar3,它是erlang的包管理器。然后,您可以使用像jsx这样的包,它允许您在二进制类型和Map之间进行转换。首先,您需要将您称为“JSON”的任何内容转换为二进制类型,可能使用tuple_to_list(),然后使用list_to_binary()。然后可以使用jsx包将二进制文件转换为Map,这样就可以从Map中提取目标值。
下面是一个例子:
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>
gijlo24d

gijlo24d4#

嗨以下你的建议是正确的我下面的代码,如果“身体”等于:

"{\"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),
     ....

我是二郎的新手。

相关问题