简体   繁体   English

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

[英]erlang JSON data - how to select only one value

in erlang language I receive this kids of JSON data:在 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"}

or或者

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

I need to select only one value per each JSON data for example: based on "BME680" value我需要 select 每个 JSON 数据只有一个值,例如:基于“BME680”值

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

or based on "SI7021" value或基于“SI7021”值

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

How can acive this task in erlang language?如何在 erlang 语言中完成这项任务? If it cold be simpler I need to extract the second value of each JSON data.如果它更简单,我需要提取每个 JSON 数据的第二个值。

For decode JSON format into Erlang format data like proplists or into the maps , you can try to use 3rd party library jiffy , then you can use simple pattern matching, eg:要将 JSON 格式解码为 Erlang 格式的数据,如proplists或映射到地图中,您可以尝试使用 3rd 方库jiffy ,然后您可以使用简单的模式匹配,例如:

Maps:地图:

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}

Proplists:道具:

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

You can use 2 modules from mochiweb project:您可以使用 mochiweb 项目中的 2 个模块:

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

Put them in some folder (fe test) and run erl shell and compile this files:将它们放在某个文件夹中(fe 测试)并运行 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}

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

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:并将 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}">>

There is a very short documentation for mochijson2, but it is easy to learn just practice in shell. mochijson2 有一个非常短的文档,但是只要在 shell 中练习就可以轻松学习。

You need to familiarize yourself with rebar3 , which is erlang's package manager.您需要熟悉rebar3 ,它是 erlang 的 package 管理器。 Then, you can use a package like jsx , which will allow you to convert between binary types and maps.然后,您可以使用package之类的 jsx ,这将允许您在二进制类型和映射之间进行转换。 First, you will need to convert whatever it is that you call "JSON" to a binary type, perhaps using tuple_to_list() then list_to_binary() , then you can use the jsx package to convert the binary to a map, which will enable you to extract the target value from the map.首先,您需要将调用“JSON”的任何内容转换为二进制类型,可能使用tuple_to_list()然后list_to_binary() ,然后您可以使用 jsx package 将二进制转换为 map,这将使您能够从 map 中提取目标值。

Here's an example:这是一个例子:

my.erl:我的.erl:

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

In the shell:在 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> 

Hi following your advice is it correct my below code if "Body" is equal to:嗨,如果“Body”等于,请按照您的建议纠正我的以下代码:

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

my code我的代码

     ....
     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),
     ....

I'm newbie in erlang.我是 erlang 的新手。

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

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