erlang JSON数据-如何仅选择一个值

问题描述

我用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数据的第二个值。

解决方法

要将JSON格式解码为Erlang格式的数据(如proplistsmaps),可以尝试使用第三方库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\",\"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}]}
,

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

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

将它们放在某个文件夹中(例如测试),然后运行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},\"TempUnit\":\"C\"}".
"{\"Time\":\"2020-08-16T15:28:55\",\"TempUnit\":\"C\"}"

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

取回您需要的物品:

5> {struct,Obj1} = proplists:get_value(<<"BME680">>,Map).
{struct,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">>,55.5}]

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

mochijson2的文档很短,但是在shell中练习很容易。

,

您需要熟悉rebar3,它是erlang的软件包管理器。然后,您可以使用jsx之类的程序包,该程序包使您可以在二进制类型和映射之间进行转换。首先,您需要将调用“ JSON”的内容转换为二进制类型,可能先使用tuple_to_list()然后使用list_to_binary(),然后可以使用jsx包将二进制转换为映射,这将使您能够从地图中提取目标值。

这是一个例子:

my.erl:

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

在外壳中:

~/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,3]}}">>.
<<"{\"A\": 100,3]}}">>

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

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

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


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

6> V1.
#{<<"x">> => 4,3]}

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

8> V2.
#{<<"a">> => 6,5]}

9> 
,

您好,按照我的建议,如果“正文”等于:是否可以纠正我的以下代码:

    "{\"Time\":\"2020-08-17T05:32:09\",\"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的新手。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...