使用 jq-shell 解析 json

json jq

问题

一个临时的需求,需要讲 pika 中的一个 SortedSet 中的数据,拷贝到另外一个 SortedSet 中。 由于,pika不支持类似 shell 的 cp 指令。所以,需要自己将数据拷贝出来,然后再写到另外一个 SortedSet中。 以前实现了一个工具,刚好可以将整个 SortedSet 以 json 格式导出来。

导出来后有两种方式解决:

  1. 在编辑器中,通过列编辑模式和查找替换,将数据最终转换成 redis-cli 的 zadd key score member [socre memeber ...]
  2. 解析json,解析中关键的字段,然后重组这些字段

方法一,以前一直在用,是延续了 Windows 的 nodepad++ 的操作方式。但是这个方式在 linux 上操作实际上是有点 low。 另外自己也要尝试下新的方法。这个时候突然想起来了,之前 龙艳 使用过 jq 这个工具。

原数据格式

[
  {
    "element": "36090685316665344",
    "score": -1499686966141,
    "binaryElement": "MzYwOTA2ODUzMTY2NjUzNDQ="
  },
  {
    "element": "36108064893437952",
    "score": -1499684590690,
    "binaryElement": "MzYxMDgwNjQ4OTM0Mzc5NTI="
  }
]

目标格式

zadd 3.1.8.1:history -1499686966141 36090685316665344 -1499684590690 36108064893437952

解决方法

最终的结果是分为两个部分的, 前面部分是固定的。关键是后面的 score member [score member ...]。 后面这个部分就需要通过 jq 这个工具来解析。

jq -j  '.[:10]|.[] | (.score|tostring)+" ", .element+" " '

jq 介绍

常规使用方法

格式化

jq . demo.json

查询

可以根据 key 查询到 value 的值。例如:

echo '{"age": 5}' | jq .age

也可以支持数组的查询, 例如:

echo '[{"age": 5}]' | jq '.[0].age'

管道操作

管道操作是 shell 的核心,也是 jq 的核心。针对每个管道,都会有输入和输出。

echo '[{"age": 5}]' | jq '.[0]| .age'

更多的介绍看下面的分享: 分享

视频

pdf

jq 工具的背景

查看了 jq 工具的作者:Stephen Dolan。是一个计算机语言的研究者,jq 就是他博士期间的作品。

查看jq 的文档, 发现提供了很多内置的函数以及流程控制。jq 也算是一门 DSL, 并且是图灵完备的。

jq 其实和 .net 中的 linq 也是很像,主要是函数式的接口吧。 jq 目前在各个平台上都有相应的实现了。

  1. java, jq-jackson
  2. node, node-jq
  3. vscode, vscode-jq
  4. go, go-jq

总结

再小的一个工具,都可以做的很好。 事情很多,可以做好的也很多。 重要的还是要“善假于物也”。

吕飞

锲而舍之,朽木不折;锲而不舍,金石可镂