Edited at

JSONにコメントを書いて前処理で消す

More than 1 year has passed since last update.


コメントのマイルール

コメントルールはとりあえずこれだけ。


  • オブジェクトのカラム名が # で始まってたらそのカラムは削除する

で、jq の walk 関数を使って以下のようにしてやるとコメントカラムが綺麗に消えてくれます。

$ jq 'walk(if type == "object" then with_entries(select(.key[0:1] != "#")) else . end)' example.json


処理例

例えばこんなJSONがあったとします。


example.json

{

"Resources": {
"AuroraDBParameterGroup": {
"Type": "AWS::RDS::DBParameterGroup",
"Properties": {
"Parameters": {

"# インデックスサイズ制限の緩和設定(Index column size too large. The maximum column size is 767 bytes. 対策)": null,
"innodb_large_prefix": "1", "# インデックスのキープレフィクスを3072バイトまで拡張出来るようにする。有効にするには更に CERATE TABLE のプションで ROW_FORMAT=DYNAMIC を付けておく":null,
"innodb_file_format": "Barracuda", "# これを使う為にはクラスタパラメータグループに binlog_format=MIXED を設定しておく必要もある":null,

"# スローログ関連設定>https://dev.mysql.com/doc/refman/5.6/ja/slow-query-log.html": null,
"# 解析ツールは mysqldumpslow とか便利":null,
"slow_query_log": "1", "# スロークエリーログを有効化。":null,
"long_query_time": "1.0", "# 0-10の範囲でマイクロ秒まで指定可能、この指定秒数以上に時間がかかったクエリが記録されるようになる":null,
"log_queries_not_using_indexes": "1", "# long_query_time以下でもインデックスを使っていないクエリは出力する":null,
"log_output": "FILE", "# Auroraのスロークエリはデフォルトで TABLE (mysql.slow_log) に吐かれる。ストアドプロシージャの実行 (CALL mysql.rds_rotate_slow_log;) で mysql.slow_query_log テーブルにローテート出来る。":null

},
"Family": {"Ref": "AuroraFamily"},
"Description": "Usual settings",
"Tags": [{"Key": "Name", "Value": {"Ref": "AWS::StackName"}} ]
}
}
}
}


↑これが、↓こうなる


output (実際はjq通した結果インデントが変わるけど比較しやすいよう体裁を修正してます)

{

"Resources": {
"AuroraDBParameterGroup": {
"Type": "AWS::RDS::DBParameterGroup",
"Properties": {
"Parameters": {
"innodb_large_prefix": "1",
"innodb_file_format": "Barracuda",
"slow_query_log": "1",
"long_query_time": "1.0",
"log_queries_not_using_indexes": "1",
"log_output": "FILE"
},
"Family": {"Ref": "AuroraFamily"},
"Description": "Usual settings",
"Tags": [{"Key": "Name", "Value": {"Ref": "AWS::StackName"}} ]
}
}
}
}


walk が実装されてない問題❗ @v1.5

jq のオンラインマニュアルに書いてあるから使えるかと思って Example 実行すると

jq: error: walk/1 is not defined at <top-level>, line 1:

walk(if type == "array" then sort else . end)
jq: 1 compile error

とかってエラーが出る…。よくよく見たらオンラインマニュアルは Developer Version なのか。現時点で最新リリース番のv1.5のマニュアルには確かに載っていない…。


自分で定義すれば使える!

しかし walk function not work #963 というIssueがあってそこで解決策が書いてあるので以下のコードを jq の式の先頭にコピペしてやればOK。

# Apply f to composite entities recursively, and to atoms

def walk(f):
. as $in
| if type == "object" then
reduce keys[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;

ところで jq スクリプト内に 行頭 # で1行コメント書けるの初めて知ったわ。長いの書く時に便利に使っていこう。


コメントカラムを消すスクリプト

walkの自前定義と最初の利用例を組み合わせて以下のようなスクリプトを作っておけば JSON からコメントを取り除くコマンドの完成だ。


jq-delete-comment.sh

#!/bin/bash

# walkはオンラインマニュアルに載ってるけどv1.5ではまだ未実装。
# しかし自分で定義すれば使える via https://github.com/stedolan/jq/issues/963
jq '
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;

# コメントカラムを削除!
walk(if type == "object" then with_entries(select(.key[0:1] != "#")) else . end)
' "$@"


これを以下のように使えばコメントカラムが消せる!

./jq-delete-comment.sh example.json


早く v1.6 をリリースしてほしい

です。