カテゴリー
【Jqコマンド活用法】JSONオブジェクトを再構成〜フィールドの一部を書き換えてみる
※ 当ページには【広告/PR】を含む場合があります。
2022/10/01

「Jqコマンド」を使っていると大抵のJSONファイルの自由度の高い編集がLinuxのターミナルから可能になります。
他方で、Jqコマンドの独特なクエリ構文になれるまでは、どのようにJSONを扱っていいものか迷うことも多々あります。
今回は、既存のJSONオブジェクトを読み込んで、その一部のフィールドを書き換え・更新するテクニックを考えてみます。
Jqのアサインメント構文を理解する
まずは本題に入る前に、Jqコマンドの
「アサインメント(Assigment)」
アサインメント操作の基本は、
『|=』
用法:
<左のJSON要素> |= <右のJSON要素>
意味:
左のJSON要素を右のJSON要素で置き換える
簡単な例で確かめると、
$ echo '{"pet":{"name":"たま","kind":"ネコ","feature":"ブチ"}}' | jq '.pet.feature |= "三毛"'
{
"pet": {
"name": "たま",
"kind": "ネコ",
"feature": "三毛"
}
}
またjq1.6以降からは、右の要素が複数していされていた場合、指定された要素のうちで最初のもの(1.6以前のバージョンでは最後のもの)で置き換わるというルールに変更されています。
#jq1.6以降のバージョン
$ echo '{"pet":{"name":"たま","kind":"ネコ","feature":"ブチ"}}' | jq '.pet.feature |= ("白毛","栗毛","三毛")'
{
"pet": {
"name": "たま",
"kind": "ネコ",
"feature": "白毛"
}
}
#jq1.5以前のバージョン
$ echo '{"pet":{"name":"たま","kind":"ネコ","feature":"ブチ"}}' | jq '.pet.feature |= ("白毛","栗毛","三毛")'
{
"pet": {
"name": "たま",
"kind": "ネコ",
"feature": "三毛"
}
}
未定義のフィールドキーで指定すると、要素の書き換えではなく、新しい要素が追加されます。
$ echo '{"pet":{"name":"たま","kind":"ネコ","feature":"ブチ"}}' | jq '.pet.age |= "5歳"'
{
"pet": {
"name": "たま",
"kind": "ネコ",
"feature": "ブチ",
"age": "5歳"
}
}
右の要素を空の要素を意味する
empty
delete
$ echo '{"pet":{"name":"たま","kind":"ネコ","feature":"ブチ"}}' | jq '.pet.name |= empty'
{
"pet": {
"kind": "ネコ",
"feature": "ブチ"
}
}
#以下でも同じ
$ echo '{"pet":{"name":"たま","kind":"ネコ","feature":"ブチ"}}' | jq 'del(.pet.name)'
{
"pet": {
"kind": "ネコ",
"feature": "ブチ"
}
}
Jqの変数のシンボリックバインドを利用する
jqコマンドで、JSONオブジェクトをより高度に編集するためには、
シンボリックバインドによって、変数としてJSONオブジェクトを利用することで、自由自在にJSONを扱うことが可能になります。
用法:
<バインドしたいJSON要素> as $<識別子> | ...
意味:
再利用したいJSON要素に識別子を使ってマークする
識別子は、
「$」
$ echo '{"owner":{"name":"山田 タロヲ","age":37,"occupation":"漁師","hobby":[{"name":"登山","carrier":"10年"},{"name":"料理","carrier":"4年"}],"pet":{"name":"たま","kind":"ネコ","feature":"ブチ"}}}' | \
jq '.owner.pet as $pet | $pet'
{
"name": "たま",
"kind": "ネコ",
"feature": "ブチ"
}
シンボリックバインドを利用することで、指定したキー(ここでは
.owner.pet
$pet
jqコマンドによる柔軟なJSONオブジェクト編集
上述してきた、
例えば、先程の例だと、飼い主と飼い猫の関係を入れ替えることを考えてみましょう。
この操作をワンライナーのjqスクリプトで表現すると以下のようになるでしょう。
$ echo '{"owner":{"name":"山田 タロヲ","age":37,"occupation":"漁師","hobby":[{"name":"登山","carrier":"10年"},{"name":"料理","carrier":"4年"}],"pet":{"name":"たま","kind":"ネコ","feature":"ブチ"}}}' |\
jq '(.owner.pet |= empty).owner as $human | .owner.pet as $pet | {"owner":$pet} | .owner.pet |= $human'
{
"owner": {
"name": "たま",
"kind": "ネコ",
"feature": "ブチ",
"pet": {
"name": "山田 タロヲ",
"age": 37,
"occupation": "漁師",
"hobby": [
{
"name": "登山",
"carrier": "10年"
},
{
"name": "料理",
"carrier": "4年"
}
]
}
}
}
一見かなり複雑なJSONオブジェクトの操作を行っているように見えますが、jqスクリプトを分解して一つ一つ考えてみると、分かりやすいかもしれません。
$ echo '{"owner":{"name":"山田 タロヲ","age":37,"occupation":"漁師","hobby":[{"name":"登山","carrier":"10年"},{"name":"料理","carrier":"4年"}],"pet":{"name":"たま","kind":"ネコ","feature":"ブチ"}}}' |\
jq '
#👇飼い主の情報だけをバインド
(.owner.pet |= empty).owner as $human |
#👇ペットの情報をバインド
.owner.pet as $pet |
#👇JSONオブジェクト全体をペットの情報から新規オブジェクトで置き換え
{"owner":$pet} |
#👇新規キーに飼い主の情報をセット
.owner.pet |= $human
'
やっていることは、更新オペレーターとシンボリックバインドオペレーターで、フィールドの値を付けたり剥がしたりしているだけです。
他には配列などから操作する「map」オペレーターも組み合わせると、非常に柔軟なJSONオブジェクトの操作がワンライナーのjqスクリプトで実現できます。
ちょっとしたJSONファイルを編集するだけなら、jqスクリプトちょちょいと作成しておくと、いざという時に便利に使えることでしょう。
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー