created: 2023-04-03T09:00:13.846Z
jq で jsonにパースできる文字列はオブジェクトにパースして出力する
たとえば、このように文字列なんだけどjsonとしてパースできるもののこと。
{
"s": "{\"b\": 1}"
}
"{\"b\": 1}"
は JSON としてパースできるので、↓のようにパースした結果を得たい。(ことが多い)
{
"s": {
"b": 1
}
}
実装
こんなjqスクリプトを書けば、JSONオブジェクトにパースできるものはパースしてくれるようになる。
with_entries(
if (
(.value | type == "string")
and (.value | fromjson? | type) == "object"
)
then
.value |= fromjson
else
.
end
)
$ echo '{"s": "{\"b\": 1}"}' | jq --from-file=/tmp/_.jq
{
"s": {
"b": 1
}
}
説明
-
with_entries()
関数は、オブジェクト内の各エントリーに対して関数を適用するもの。このスクリプトでは、各エントリーに対して後述の関数を適用することで、オブジェクト内の値を処理することになる。 -
if
文は、条件分岐を行うためのもの。このスクリプトでは、以下の条件で分岐している。(.value | type == "string")
: 値が文字列である場合and (.value | fromjson? | type) == "object"
: 値をJSONパースした結果がオブジェクトである場合。つまりJSONとしてパース可能である場合
-
then
ブロックは、条件が真である場合に実行される処理.value
をJSONパースした結果を再度.value
に代入している|=
は代入を行う二項演算子
-
else
ブロックは、条件が偽である場合に実行される。このスクリプトでは、.value
をそのまま返す。