jqを利用してエスケープ処理済みのJSON文字列を作成する方法

2021.08.16

こんにちは!DA(データアナリティクス)事業本部 サービスソリューション部の大高です。

本エントリでは、jqを利用してエスケープ処理済みのJSON文字列を作成する方法を紹介したいと思います。

結論

結論から言うと、下記のようなコマンドで作成できます。

$ cat event-detail.json | jq '@json' > escaped-event-detail.json

やりたいこと

たとえば、AWS CLIを利用する時などに、以下のようなリクエスト形式を持つAPIがあります。

[
  {
    "Time": timestamp,
    "Source": "string",
    "Resources": ["string", ...],
    "DetailType": "string",
    "Detail": "string",
    "EventBusName": "string",
    "TraceHeader": "string"
  }
  ...
]

この時、DetailにJSON形式の値を指定したいことはありませんか?わたしはあります。

例えば、Detailに指定したい値が以下のようなJSONだったとします。

{
  "name": "foo-bar",
  "details": {
    "fields": [
      { "name": "name1", "val": "val1" },
      { "name": "name2", "val": "val2" },
      { "name": "name3", "val": "val3" }
    ]
  }
}

この場合、以下のようにコマンドを実行しますが、

$ aws events put-events --entries file://putevents.json

putevents.jsonの中身は以下のようにはできません。

NG-putevents.json

[
  {
    "Source": "com.mycompany.myapp",
    "Detail": {
      "name": "foo-bar",
      "details": {
        "fields": [
          { "name": "name1", "val": "val1" },
          { "name": "name2", "val": "val2" },
          { "name": "name3", "val": "val3" }
        ]
      }
    },
    "Resources": [
      "resource1",
      "resource2"
    ],
    "DetailType": "myDetailType"
  }
]

正しくは、以下になります。

OK-putevents.json

[
  {
    "Source": "com.mycompany.myapp",
    "Detail": "{\"name\":\"foo-bar\",\"details\":{\"fields\":[{\"name\":\"name1\",\"val\":\"val1\"},{\"name\":\"name2\",\"val\":\"val2\"},{\"name\":\"name3\",\"val\":\"val3\"}]}}",
    "Resources": [
      "resource1",
      "resource2"
    ],
    "DetailType": "myDetailType"
  }
]

このように、JSON文字列を指定する場合は、改行をなくしたり、エスケープ処理をした文字列を指定する必要がありますが「手動でやるのは辛いのでどうにかしたい!」というのが今回の趣旨になります。

jqを使って対応する

必要な処理としては、2つです。

1つは、JSONを1行のコンパクトな形式にすること。もう1つは、ダブルクォーテーションなどの文字をエスケープすることです。

これらはjqの@jsonを利用することで、以下のように対応できます。

$ cat event-detail.json | jq '@json'
"{\"name\":\"foo-bar\",\"details\":{\"fields\":[{\"name\":\"name1\",\"val\":\"val1\"},{\"name\":\"name2\",\"val\":\"val2\"},{\"name\":\"name3\",\"val\":\"val3\"}]}}"

あとはこの結果をファイルに出力したり、適宜加工してあげることで前述のputevents.jsonを作成しておわりです。簡単ですね。

まとめ

以上、jqを利用してエスケープ処理済みのJSON文字列を作成する方法でした。

最初はこの方法を知らなくてエディタの文字列置換でやろうかと思ったのですが、さすがに面倒なので調べたところjqによいオプションがあることを知りました。jq便利ですね。

どなたかのお役に立てば幸いです。それでは!

参考