JSONの中に文字列として記載されたJSONの値をjqで扱ってみる

JSONの中のある文字列のJSONをjqで扱うテクニック
2020.10.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

好物はインフラとフロントエンドのかじわらゆたかです。 StepFunctionsでの値の受け渡しや、S3のPut EventをSNS経由で連携した時等JSONの項目の中に文字列でJSONが含まれることがあります。 これらをjqで確認する方法になります。

やってみた

以下のJSONを対象とします。

{
    "Error": "InvalidElasticIpFault",
    "Cause": "{\"errorMessage\": \"An error occurred (InvalidElasticIpFault) when calling the RestoreFromClusterSnapshot operation: The Elastic IP address aa.bbb.ccc.ddd is already associated with another instance.\", \"errorType\": \"InvalidElasticIpFault\", \"stackTrace\": [\"  省略\\n\", \"  File \\\"/var/runtime/botocore/client.py\\\", line 316, in _api_call\\n    return self._make_api_call(operation_name, kwargs)\\n\", \"  File \\\"/var/runtime/botocore/client.py\\\", line 635, in _make_api_call\\n    raise error_class(parsed_response, operation_name)\\n\"]}"
}

Cause内の文字列にJSONが格納されているのがわかるかと思います。 普通に読んでいけば内容はわかりますが、例えば報告等をする際にこの文字列をそのまま貼り付けるのは読み手のことを考えていないことになりますし、 この文字列を手で改行等入れるのは骨が折れる作業となります。

そういった際には、上記のJSONをファイルとして保存し、以下のコマンドで整形することが可能です

cat ./message.json | jq -r .Cause | jq .

上記のJSONをmessage.jsonとして保存し、実行した結果が以下になります。

$ sh outputMessage.sh
{
  "errorMessage": "An error occurred (InvalidElasticIpFault) when calling the RestoreFromClusterSnapshot operation: The Elastic IP address aa.bbb.ccc.ddd is already associated with another instance.",
  "errorType": "InvalidElasticIpFault",
  "stackTrace": [
    "  省略\n",
    "  File \"/var/runtime/botocore/client.py\", line 316, in _api_call\n    return self._make_api_call(operation_name, kwargs)\n",
    "  File \"/var/runtime/botocore/client.py\", line 635, in _make_api_call\n    raise error_class(parsed_response, operation_name)\n"
  ]
}

これなら読み手にこの内容を伝える際に、ただ貼り付けただけの内容に比べて読み手のことを考えた内容であると言えると思います。

結論

JSONの中に文字列でJSONが含まれるケースはちょくちょくあるかと思います。 そういった際に、簡単に内容を取り出すテクニックとして活用いただければ幸いです。