如何从 JSON 文件中提取数据

如何从 JSON 文件中提取数据

我一直在寻找我的问题的解决方案,但没有找到一个或更好的说法,我没有用我找到的东西得到它。我的问题是:我正在 Raspberry Pi 上使用智能家居控制软件。使用pilight-receive,我可以从室外温度传感器捕获数据。 pilight-receive 的输出如下所示:

{
        "message": {
                "id": 4095,
                "temperature": 409.5
        },
        "origin": "receiver",
        "protocol": "alecto_wsd17",
        "uuid": "0000-b8-27-eb-0f3db7",
        "repeats": 3
}
{
        "message": {
                "id": 1490,
                "temperature": 25.1,
                "humidity": 40.0,
                "battery": 1
        },
        "origin": "receiver",
        "protocol": "alecto_ws1700",
        "uuid": "0000-b8-27-eb-0f3db7",
        "repeats": 3
}
{
        "message": {
                "id": 2039,
                "temperature": 409.5
        },
        "origin": "receiver",
        "protocol": "alecto_wsd17",
        "uuid": "0000-b8-27-eb-0f3db7",
        "repeats": 4
}

现在我的问题是:如何从 id 为 1490 的消息中提取温度和湿度?您建议我如何经常进行检查?通过每 10 分钟运行一次的 cron 作业,创建 的输出pilight-receive,提取输出的数据并将其推送到智能家居控制 API?

答案1

您可以使用jqshell 中处理 json 文件。

例如,我将示例 json 文件保存为raul.json然后运行:

$ jq .message.temperature raul.json 
409.5
25.1
409.5
$ jq .message.humidity raul.json 
null
40
null

杰克可以为大多数 Linux 发行版预先打包。

本身可能有一种方法可以做到这一点jq,但我发现在一行上获取两个所需值的最简单方法是使用xargs.例如:

$ jq 'select(.message.id == 1490) | .message.temperature, .message.humidity' raul.json | xargs
25.1 40

或者,如果您想循环遍历每个.message.id实例,我们可以添加.message.id到输出并使用,xargs -n 3因为我们知道将有三个字段(id、温度、湿度):

jq '.message.id, .message.temperature, .message.humidity' raul.json | xargs -n 3
4095 409.5 null
1490 25.1 40
2039 409.5 null

然后您可以使用 awk 或其他方式对该输出进行后处理。


最后,python 和 perl 都有优秀的库用于解析和操作 json 数据。与其他几种语言一样,包括 php 和 java。

答案2

对于那些不太了解高级功能的人awk(例如像我这样的人)并且没有jq预安装的人,一个简单的解决方案是将几个本机命令通过管道连接在一起,如下所示:

grep -A2 '"id": 1490,' stats.json | sed '/1490/d;s/"//g;s/,//;s/\s*//'

如果您只是想获取值,那么使用grep而不是awkor会更容易sed

grep -A2 '"id": 1490,' stats.json | grep -o "[0-9]*\.[0-9]*"

为了提供解释,这对我来说似乎是最简单的方法。

  • grep -A2会抓取您在 JSON 中查找的行以及以下两行,其中包含温度和湿度。
  • 管道grep -o仅打印由 a 分隔的数字.(这永远不会出现在第一1490行,因此您只剩下 2 个值 - 温度和湿度。非常简单。jq在我看来,甚至比使用 更简单。

答案3

我选择的在命令行上处理 JSON 的工具是 jq。但是,如果您没有安装 jq,则可以很好地使用 Perl:

# perl -MJSON -e '$/ = undef; my $data = <>; for my $hash (new JSON->incr_parse($data)) { my $msg = $hash->{message}; print "$msg->{temperature} $msg->{humidity}\n" if $msg->{id} == 1490 }' < data.json
25.1 40

答案4

您的输出是一组 JSON 片段,而不是完整的 JSON。如果/一旦您将输出重新排列为完整的 JSON,例如像这样(假设您的输出位于 中file.json):

echo "[ $(cat file.json | sed -E 's/^}$/},/; $d') }]"

然后就可以使用jtc工具轻松实现您想要的目标(可在以下位置获得:https://github.com/ldn-softdev/jtc):

bash $ echo "[ $(cat file.json | sed -E 's/^}$/},/; $d') }]" | jtc -x "[id]:<1490>d [-1]" -y[temperature] -y[humidity] -l
"temperature": 25.1
"humidity": 40.0
bash $ 

在上面的示例中,-l如果您不需要打印标签,请删除

相关内容