たとえばSlackの Incoming Webhook でメッセージを送るときに、メッセージ部分だけを置き換えてJSONを組み立てたいことがあります。
プログラミング言語が使えるなら簡単なんですが、ちょっと大げさな気もするので jq だけでJSONを組み立てられるとべんりそうです。
{"text":"hi"}
このようなJSONを組み立てて送信したいとして、"hi"
の部分を変数にしてみます。
{"text":$text}
この $text
の部分を任意の文字列に置き換えるには --arg オプションを使います。(-n / -c)
$ jq -n -c --arg text hi '{"text":$text}'
{"text":"hi"}
今回のケースでは不要ですが文字列以外の値に置き換えるには --argjson オプションを使うことが出来ます。
$ jq -n -c --argjson text 12345 '{"text":$text}'
{"text":12345}
目的はこのJSONをSlackに投げることだったので生成結果を curl に食わせます。 -d @- で標準入力をbodyとして送信できるのではこれを利用します。
ちなみに Object Construction が使えるので { text: $text }
のような書き方が出来ることも覚えておくとよさそうです。
$ jq -n -c --arg text hi '{ text: $text }' | curl -H 'Content-Type: application/json' -d @- <Incoming Webhook URL>
これで目的は達することが出来ました。
Slackに投稿するときは、恐らくもうちょと 複雑なメッセージを組み立てる 必要があると思います。
そういった場合にはテンプレートとしてファイルを用意しておきそれを読み込むことも出来ます。
以下のような内容で template.js
というファイルを用意します。.js
拡張子なのは object っぽい書き方なのでシンタックスハイライトが効くから。。。
{
blocks: [
{
type: "header",
text: {
type: "plain_text",
text: "CI"
},
},
{
type: "section",
fields: [
{
type: "mrkdwn",
text: "*Result:*\n\($result)"
},
{
type: "mrkdwn",
text: "*SHA1:*\n\($sha1)"
}
]
}
]
}
ファイルを受け取るには -f オプションが使えるので以下のようにして生成します。
jq -c -n --arg result Success --arg sha1 eeeaaa -f template.js | curl -S -H 'Content-Type: application/json' -d @- <Incoming Webhook URL>
ちなみに gojq でももちろん同じことが出来て圧倒的に速いので、大きなJSONを生成するときはおすすめです。
$ time gojq -c -n --arg result Success --arg sha1 eeeaaa -f template.js > /dev/null
________________________________________________________
Executed in 7.56 millis fish external
usr time 2.54 millis 0.09 millis 2.45 millis
sys time 3.83 millis 1.12 millis 2.71 millis
$ time jq -c -n --arg result Success --arg sha1 eeeaaa -f template.js > /dev/null
________________________________________________________
Executed in 31.71 millis fish external
usr time 40.19 millis 0.12 millis 40.07 millis
sys time 10.60 millis 1.06 millis 9.53 millis