BashでJSONをフォーマットする方法:jq完全ガイド

·SRE & Shell Scripting Specialist·レビュー担当Erik Lindqvist·公開日

無料の JSON整形ツール をブラウザで直接使用 — インストール不要。

JSON整形ツール をオンラインで試す →

デプロイスクリプトが API レスポンスの処理や CI での設定ファイルの検証を始めると、 bash で JSON をフォーマットする方法を知ることが すぐに不可欠になります。 実際のユースケースの 99% をカバーする 2 つのツールは jq python3 -m json.tool です — どちらも bash の JSON フォーマットパイプラインを確実に処理し、 終了コードで検証し、CI/CD ワークフローにクリーンに統合できます。 ターミナルなしで素早く確認したい場合は、ブラウザベースの JSON Formatter が即座に対応します。このガイドでは、jq のインストール、パイプとファイルのフォーマット、 検証関数、GitHub Actions での CI/CD 統合、pre-commit フック、heredoc パターン、 そして Python 標準ライブラリへのフォールバックのタイミングについて説明します。

ポイント
  • jq . はフォーマットと検証を同時に実行 — 無効な JSON の場合は終了コード 1 で終了
  • • CI パイプラインでは jq -e を使用:出力が空/false/null の場合に非ゼロ終了
  • jq . file.json > /dev/null && echo "valid" — 出力を変えずに検証のみ実施
  • python3 -m json.tool は追加インストール不要でどのシステムでも動作
  • jq . f.json > f.json は絶対にしないこと — シェルが jq の読み取り前にソースファイルを切り詰めてしまう

bash における JSON フォーマットとは?

bash での JSON フォーマットとは、コンパクトに圧縮された JSON を、 インデントされた人間が読みやすい出力に変換することです。 基になるデータは変わらず — 空白と改行だけが異なります。 スクリプトのコンテキストでこれが重要な理由は 2 つあります: デバッグ時の可読性と、フォーマッターが副作用として構文チェックを行う場合の検証性です。 jq のようなツールは再フォーマットの前に JSON を完全にパースするため、 フォーマットが成功すれば同時に有効性の確認にもなります。 このフォーマットと検証を 1 ステップで行うという二重の挙動こそが、 jq を自動化パイプラインで非常に有用にしている理由です。

Before · json
After · json
{"service":"payments-api","version":"2.4.1","database":{"host":"db-prod-01.internal","port":5432,"pool_size":20},"cache":{"enabled":true,"ttl":300}}
{
  "service": "payments-api",
  "version": "2.4.1",
  "database": {
    "host": "db-prod-01.internal",
    "port": 5432,
    "pool_size": 20
  },
  "cache": {
    "enabled": true,
    "ttl": 300
  }
}

jq — bash で JSON をフォーマットする

jq は シェルスクリプトにおける JSON 処理のデファクトスタンダードです(jq 1.6+、bash 4+)。 JSON のフォーマット、フィルタリング、変換、検証ができる専用のコマンドライン JSON プロセッサです。 恒等フィルター . は入力をそのまま通しますが、フォーマットされた状態で出力します。 jq が入力をパースできない場合、終了コード 1 で終了します — これがスクリプトに最適な理由です:フォーマットと検証が 1 つの操作で完結します。

jq のインストール

Bash
# macOS
brew install jq

# Debian / Ubuntu
apt-get install -y jq

# Fedora / RHEL / CentOS
dnf install jq

# Alpine (Docker images)
apk add --no-cache jq

# Verify
jq --version  # jq-1.7.1

stdin とファイルからのフォーマット

Bash
# Pipe inline JSON through jq
echo '{"host":"db-prod-01.internal","port":5432}' | jq .

# Format a file directly (prints to stdout)
jq . config/feature-flags.json

# Format with 4-space indentation
jq --indent 4 . config/feature-flags.json

# Format using tabs instead of spaces
jq --tab . config/feature-flags.json

フォーマット済み出力をファイルに書き込む

Bash
# Save formatted output (do NOT redirect back to the same file)
jq . compact.json > formatted.json

# Compact (minify) — reverse of formatting
jq -c . formatted.json
注意:jq は 無効な JSON の場合は終了コード 1、成功時は 0、使用エラーの場合は 5 で終了します。スクリプト全体の if 文や || exit 1 ガードでこれを活用してください。

キーのソートとカラー出力の無効化

Bash
# Sort all keys alphabetically (useful for deterministic diffs)
jq --sort-keys . config/app-config.json

# Disable colour output when writing to a log file
jq --monochrome-output . response.json >> deploy.log

jq オプションリファレンス

フォーマットと検証ワークフローで最もよく使われる jq フラグ:

オプション
デフォルト
説明
.
フィルター
恒等フィルター — 入力全体をそのままフォーマットして出力します。
--indent N
整数
2
インデントを N スペースに設定します(0〜7)。標準は 2 または 4。
--tab
フラグ
オフ
スペースの代わりにタブ文字でインデントします。
-c / --compact-output
フラグ
オフ
出力を 1 行に折りたたみます(最小化)。整形を元に戻します。
-r / --raw-output
フラグ
オフ
JSON の引用符なしで文字列を出力します。プレーンテキスト値の抽出に便利です。
-e / --exit-status
フラグ
オフ
出力が false または null の場合、終了コード 1 で終了します。CI アサーションに最適です。
-M / --monochrome-output
フラグ
オフ
カラー出力を無効にします — ファイルや非ターミナルへのパイプ時に便利です。
-S / --sort-keys
フラグ
オフ
すべてのネストレベルでオブジェクトのキーをアルファベット順にソートします。
-n / --null-input
フラグ
オフ
入力を読み取らず、--arg / --argjson で JSON をゼロから構築します。
--arg name val
文字列
シェル文字列を名前付き jq 変数($name)としてバインドし、フィルター内でアクセス可能にします。

bash スクリプトで JSON を検証する

jq では検証とフォーマットは同じ操作です — 出力前にパースします。 フォーマット済みの出力は不要で終了コードだけが必要な場合は、 stdout を /dev/null にリダイレクトします。以下のパターンはデプロイスクリプト、pre-commit フック、 CI パイプラインで再利用できます。 インシデント対応において、見慣れない API ペイロードに遭遇したとき、 まず jq にパイプするのが私のやり方です — 圧縮された JSON の塊を、実際に読んでデバッグできる形式に変換してくれます。

再利用可能な検証関数

Bash
validate_json() {
  local file="$1"
  if jq . "$file" > /dev/null 2>&1; then
    echo "✓ Valid JSON: $file"
    return 0
  else
    echo "✗ Invalid JSON: $file" >&2
    return 1
  fi
}

無効な設定でデプロイを中断する

Bash
CONFIG="infra/k8s/app-config.json"
validate_json "$CONFIG" || { echo "Aborting deploy: invalid config" >&2; exit 1; }

ディレクトリ内のすべての JSON ファイルを検証する

Bash
find ./config -name "*.json" | while read -r f; do
  jq . "$f" > /dev/null 2>&1 || echo "INVALID: $f"
done
注意:-e / --exit-status フラグは さらに一歩踏み込みます:出力 false または null の場合にも 終了コード 1 で終了します。 特定のフィールドが真であることを確認するのに使えます: jq -e '.feature_flags.new_checkout' config.json

ファイルと API レスポンスから JSON をフォーマットする

シェルスクリプトで JSON の一般的なソースは 2 つあります:ディスク上のファイルと curl 経由の HTTP API レスポンスです。それぞれ処理パターンが若干異なります。 ファイルの場合、主な関心事は安全なインプレース編集です。 API レスポンスの場合、重要なのは curl のプログレスバーを抑制して jq の入力を汚染しないようにすることです。

ファイルの安全なインプレースフォーマット

Bash
# Format and overwrite safely using a temp file
tmp=$(mktemp)
jq --indent 2 . config/feature-flags.json > "$tmp" && mv "$tmp" config/feature-flags.json
echo "Formatted config/feature-flags.json"

curl の API レスポンスをフォーマットする

Bash
# Format deployment status from API
DEPLOY_ID="dep_8f3a2b9c"
curl -s \
  -H "Authorization: Bearer $DEPLOY_API_TOKEN" \
  "https://api.deployments.internal/v1/deploys/$DEPLOY_ID" \
  | jq --indent 2 .

フォーマットとフィルタリングを同時に行う

Bash
# Get formatted + filter to errors only from a monitoring endpoint
curl -s "https://monitoring.internal/api/events?level=error&limit=10" \
  | jq '[.events[] | {id, message, timestamp, service}]' \
  || { echo "Failed to fetch or parse events" >&2; exit 1; }

ここでの || { ... } パターンは非常に重要です。これがなければ、curl の失敗や不正な API レスポンスが 静かに通過し、スクリプトの次のステップが空または部分的なデータで動作してしまいます。 フィルター式を最初に書かずに複雑なネストされたレスポンスを調べる必要がある場合は、 ブラウザベースの JSON Formatter を使えば生のレスポンスを貼り付けてツリーをインタラクティブに探索できます。

CI/CD パイプラインで JSON をフォーマットする

CI こそ JSON 検証ゲートが最も重要な場所です — 本番環境に到達した不正な設定のロールバックは、パイプライン失敗よりはるかに痛みを伴います。 多くの情報源は jq を 1 回限りのターミナル使用として説明していますが、 以下のパターンは私が本番の SRE ワークフローで設定エラーがデプロイスロットに到達する前に キャッチするために実際に使っているものです。

GitHub Actions — すべての JSON 設定を検証する

YAML
- name: Validate JSON configs
  run: |
    echo "Validating JSON configuration files..."
    find . -name "*.json" -not -path "*/node_modules/*" | while read -r f; do
      if ! jq . "$f" > /dev/null 2>&1; then
        echo "::error file=$f::Invalid JSON syntax"
        exit 1
      fi
    done
    echo "All JSON files are valid"

pre-commit フック — ステージングされた JSON ファイルを検証する

Bash
#!/usr/bin/env bash
set -euo pipefail
STAGED=$(git diff --cached --name-only --diff-filter=ACM | grep '\.json$' || true)
[ -z "$STAGED" ] && exit 0
for f in $STAGED; do
  jq . "$f" > /dev/null 2>&1 || { echo "Invalid JSON: $f"; exit 1; }
done
echo "JSON validation passed"
注意:pre-commit フックを scripts/validate-json.sh に保存し、 chmod +x scripts/validate-json.sh で実行可能にして、シンボリックリンクを作成します: ln -s ../../scripts/validate-json.sh .git/hooks/pre-commit

bash で JSON 変数と Heredoc をフォーマットする

シェルスクリプトは環境変数、git メタデータ、または計算値から動的に JSON ペイロードを 構築することがよくあります。最も安全なパターンは文字列補間ではなく jq -n --arg / --argjson を使用することです — 値に引用符や改行が含まれた瞬間に文字列補間は壊れます。 JSON の空白による単語分割を防ぐために、jq にパイプする際は変数を必ずダブルクォートで囲んでください。

保存された API レスポンス変数をフォーマットする

Bash
# Always quote "$API_RESPONSE" — whitespace in JSON would break an unquoted expansion
echo "$API_RESPONSE" | jq --indent 2 .

jq -n でペイロードを構築してフォーマットする

Bash
payload=$(jq -n \
  --arg env "production" \
  --arg version "$(git describe --tags)" \
  --argjson replicas 3 \
  '{environment: $env, version: $version, replicas: $replicas}')

# Inspect the built payload
echo "$payload" | jq .

# Post it to an API
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $DEPLOY_API_TOKEN" \
  -d "$payload" \
  "https://api.deployments.internal/v1/deploys"
注意:--arg は常に 文字列値をバインドします。 --argjson は 値を先に JSON としてパースするので、フィルター式内でクォートせずに 数値、真偽値、配列、オブジェクトを渡せます。

jq をインストールせずに bash で JSON をフォーマットする

jq が利用できない場合 — 最小限の Docker イメージ、制限された CI ランナー、 またはパッケージをインストールできないシステム — Python の組み込み json.tool モジュールが同じコア機能を提供します。Python 標準ライブラリの一部であり、 Python 3 がインストールされていれば追加の依存関係なしで動作します。

Bash
# Format from a file
python3 -m json.tool config.json

# Control indent width
python3 -m json.tool --indent 2 config.json

# Sort keys alphabetically
python3 -m json.tool --sort-keys config.json

# Format from stdin (e.g., piped from curl)
curl -s https://api.deployments.internal/v1/status | python3 -m json.tool
警告:python3 -m json.tool は jq より厳格です:末尾のカンマ、コメント、JSON5 拡張を拒否します。 この厳格さは本番設定の検証には望ましいですが、 サードパーティツールの緩い JSON を扱う際に摩擦になることがあります。 また、カラー出力がないため、インタラクティブな使用では jq よりターミナル検査の使い勝手が劣ります。
Bash
# Validation with exit code (same semantics as jq)
python3 -m json.tool config.json > /dev/null && echo "valid" || echo "invalid"

# Inline string validation
echo '{"service":"payments-api","healthy":true}' | python3 -m json.tool > /dev/null
echo "Exit code: $?"  # 0 = valid

シンタックスハイライト付きのターミナル出力

jq はデフォルトで 出力に色を付けます — キーは青、文字列は緑、数値は白。 スクロール可能なページャーで完全な JSON シンタックスハイライトが必要な場合や、 ターミナルセッションで大きなネストされたレスポンスをデバッグする場合は、 bat が最も使い勝手の良い体験を提供します。どちらもデバッグとインタラクティブな検査に便利ですが、 ファイルや API レスポンスに出力を書き込む場合はどちらも使用すべきではありません。

bat のインストール

Bash
# macOS
brew install bat

# Debian / Ubuntu (binary may be named batcat — alias if so)
apt-get install -y bat
# alias bat=batcat   # add to ~/.bashrc if needed

# Verify
bat --version  # bat 0.24.0

シンタックスハイライト付きで JSON ファイルを表示する

Bash
# Syntax-highlighted JSON in the pager (press q to exit)
bat config/app-config.json

# Disable paging — print directly to terminal
bat --paging=never config/app-config.json

# Pipe jq output through bat for coloured inspection
jq '.database' infra/app-config.json | bat --language=json --paging=never

スクロール可能なページャーでカラー jq 出力を見る

Bash
# -C forces color even when stdout is not a tty (e.g. when piping to less)
jq -C . logs/deploy-response.json | less -R
警告:カラー出力(bat / jq -C)は ターミナルの検査とデバッグにのみ使用してください。 ログファイルへの書き込みや他のツールへのパイプ前には ANSI カラーコードを除去してください —jq -M . --monochrome-output) または bat --plain を使用してください。

bash で大きな JSON ファイルを扱う

JSON ファイルが 50〜100 MB を超えると、jq のデフォルトモードでメモリに読み込むと 遅くなったり、メモリが制限されたホスト(たとえば 512 MB 制限の Docker コンテナ)では OOM が発生したりする可能性があります。 jq --stream はドキュメント全体をバッファリングせず、読み取りながらパス/値のペアを増分的に出力します。 NDJSON(1 行に 1 つの JSON オブジェクト)には、jq にはより効率的なネイティブなアプローチがあります。

jq --stream で大きな JSON ファイルをストリーミングする

Bash
# --stream emits [path, scalar] pairs as jq reads the input
# Extract all "status" fields from a large log archive without loading it fully
jq -c --stream   'if length == 2 and (.[0][-1] == "status") then .[1] else empty end'   logs/archive-2026-03.json

NDJSON / JSON Lines — 1 行ずつオブジェクトを処理する

Bash
# NDJSON: one JSON object per line — common in Kafka exports, Fluentd, and Logstash
# -R reads raw lines; fromjson? skips lines that are not valid JSON
jq -c -R 'fromjson? | {id: .request_id, status: .http_status, latency: .duration_ms}'   logs/access-2026-03-13.ndjson > logs/summary.ndjson
Bash
# Shell loop alternative — useful when you need per-line error handling
while IFS= read -r line; do
  echo "$line" | jq -c '{id: .request_id, status: .http_status}' 2>/dev/null ||     echo "SKIP: malformed line" >&2
done < logs/access-2026-03-13.ndjson
注意:ファイルが 50〜100 MB より大きい場合、またはプロセスがメモリ制限のあるコンテナ内で 実行される場合は、標準の jq . file.json から --stream に切り替えてください。 NDJSON パイプラインでは、シェルの while read ループより jq -R 'fromjson?' を優先してください — 行ごとにサブシェルを生成しないため、大幅に高速です。

よくあるミス

シェルリダイレクトでソースファイルを上書きしてしまう

問題: シェルは jq が入力を読み取る前に出力ファイルを開いて切り詰めます。ソースと出力が同じパスの場合、jq は空のファイルを読み取ることになります。

修正方法: まず mktemp 一時ファイルに書き込み、mv でアトミックに元のファイルを置き換えます。

Before · Bash
After · Bash
jq --indent 2 . settings.json > settings.json
tmp=$(mktemp) && jq --indent 2 . settings.json > "$tmp" && mv "$tmp" settings.json
スクリプトで jq の失敗を処理しない

問題: エラーハンドラーがない場合、JSON が無効なときにスクリプトは空または欠損したフォーマット済みファイルで静かに続行します — 後続のステップが分かりにくいエラーで失敗します。

修正方法: 後のステップで使用される出力を生成するすべての jq 呼び出しの後に || { echo '...' >&2; exit 1; } を追加します。

Before · Bash
After · Bash
jq . response.json > formatted.json
jq . response.json > formatted.json || { echo "Invalid JSON in response.json" >&2; exit 1; }
curl に -s を渡し忘れる

問題: curl はデフォルトでプログレスバーを stderr に出力します。stderr が stdout とマージされる場合(サブシェルやログキャプチャなど)、プログレスバーのテキストが jq の入力に現れて解析エラーを引き起こします。

修正方法: jq にパイプするときは curl に必ず -s(サイレント)を渡してください。診断出力が必要な場合は -v や --fail-with-body を別途使用してください。

Before · Bash
After · Bash
curl https://api.payments.internal/config | jq .
curl -s https://api.payments.internal/config | jq .
jq -r . でフォーマットされた JSON を期待する

問題: -r / --raw-output フラグはトップレベルの文字列値から JSON クォートを取り除くだけで、オブジェクトや配列をフォーマットしません。オブジェクト入力に -r . を渡しても、インデントされた出力ではなく同じコンパクトなオブジェクトが生成されます。

修正方法: フォーマットには jq .(-r フラグなし)を使用します。-r は jq -r '.version' config.json のようなプレーン文字列値の抽出に限定してください。

Before · Bash
After · Bash
jq -r . config.json
jq . config.json

jq vs python3 vs json_pp — クイック比較

ツールの選択は、環境で何が利用可能か、そして基本的なフォーマット以外に何が必要かによって異なります:

ツール
検証
カラー表示
CI対応
終了コード
インデント制御
インストール
jq
✅ (code 1)
✅ --indent N
brew / apt / dnf
python3 -m json.tool
✅ (厳格)
✅ (code 1)
✅ --indent N
組み込み(Python)
json_pp (Perl)
⚠️ 部分的
⚠️ 不定
組み込み(Perl)
fx (Node.js)
⚠️ 部分的
⚠️ 限定的
npm install -g fx
node -e JSON.parse
✅ JSON.stringify
組み込み(Node.js)

ほとんどの bash スクリプトと CI/CD 作業では、jq が正しいデフォルト選択です — 追加のランタイム依存なしに、単一のバイナリで検証、フォーマット、フィルタリング、 信頼性の高い終了コードを提供します。追加パッケージをインストールできず Python がすでに存在する場合は python3 -m json.tool にフォールバックしてください。

よくある質問

bash で JSON ファイルをその場でフォーマットするにはどうすればよいですか?

jq の出力を同じファイルにリダイレクトしてはいけません — シェルは jq が読み取る前にファイルを切り詰めてしまいます。代わりに、まず一時ファイルに書き込み、mv でアトミックに元のファイルを置き換えてください。

Bash
tmp=$(mktemp)
jq --indent 2 . config/app-config.json > "$tmp" && mv "$tmp" config/app-config.json
echo "正常にインプレースでフォーマットしました"

bash スクリプトで JSON を検証し、エラー時に終了するにはどうすればよいですか?

ファイルをパイプまたは引数として jq に渡し、stdout を /dev/null にリダイレクトします。|| を使って非ゼロ終了を捕捉し、スクリプトを中断します。jq は解析エラー時に終了コード 1 で終了するため、CI ゲートとして信頼性があります。

Bash
validate_json() {
  local file="$1"
  if jq . "$file" > /dev/null 2>&1; then
    echo "✓ Valid JSON: $file"
    return 0
  else
    echo "✗ Invalid JSON: $file" >&2
    return 1
  fi
}

validate_json infra/k8s/app-config.json || exit 1

jq をインストールせずに bash で JSON をフォーマットするにはどうすればよいですか?

python3 の組み込み json.tool モジュールを使用してください — 標準的な Python インストールに同梱されており、jq と同じ終了コードのセマンティクスで適切にインデントされた出力を生成します。

Bash
# Format from a file
python3 -m json.tool config.json

# Format from stdin (e.g., a curl response)
curl -s https://api.internal/status | python3 -m json.tool --indent 2

bash で curl のレスポンスを JSON フォーマットするにはどうすればよいですか?

curl には必ず -s(サイレント)を渡して、プログレスバーが jq の入力を汚染しないようにしてください。curl の stdout を直接 jq にパイプします。

Bash
DEPLOY_ID="dep_8f3a2b9c"
curl -s \
  -H "Authorization: Bearer $DEPLOY_API_TOKEN" \
  "https://api.deployments.internal/v1/deploys/$DEPLOY_ID" \
  | jq --indent 2 .

jq を使って JSON ファイルの一部だけをフォーマットするにはどうすればよいですか?

恒等フィルター(.)の代わりに jq のパス式を使って、ネストされたオブジェクトや配列を抽出してフォーマットします。結果自体がフォーマットされた JSON になります。

Bash
# Format just the database config block
jq --indent 2 '.database' infra/app-config.json

# Format + filter events array to error level only
jq '[.events[] | select(.level == "error") | {id, message, service}]' events.json

無効な JSON に対して jq はどの終了コードを返しますか?

jq は解析エラーに対して終了コード 1 を返します。また、-e / --exit-status フラグが設定されていて出力が false または null の場合も終了コード 1 を返します。終了コード 0 は有効な JSON が解析され、真の出力が生成されたことを意味します。終了コード 5 はシステムが使用エラーに遭遇したことを意味します。

Bash
# Test exit code directly
echo '{"ok":true}' | jq . > /dev/null 2>&1; echo "exit: $?"  # exit: 0
echo '{bad json}' | jq . > /dev/null 2>&1; echo "exit: $?"   # exit: 1

# -e flag: exit 1 if output is false/null
echo 'null' | jq -e . > /dev/null 2>&1; echo "exit: $?"      # exit: 1

関連ツール

bash JSON フォーマットのブラウザベースの代替ツールと補完ツール — ビジュアルインターフェース、共有可能なリンク、またはターミナル外での作業が必要な場合に便利です:

他の言語でも利用可能:PythonGoJavaScript
NO
Nadia OkonkwoSRE & Shell Scripting Specialist

Nadia is a site reliability engineer who lives in the terminal. She writes Bash scripts that process logs, transform data, and orchestrate infrastructure across fleets of servers. She is a heavy user of jq, awk, and sed and writes about shell one-liners, text processing pipelines, data serialisation from the command line, and the practical Bash patterns that SREs reach for when speed matters more than elegance.

EL
Erik Lindqvist技術レビュアー

Erik is a DevOps engineer who has spent years writing and maintaining the shell scripts that hold CI/CD pipelines together. He writes about Bash best practices, portable POSIX shell, encoding and decoding in shell scripts, secret management from the command line, and the patterns that separate reliable automation scripts from brittle ones. He is a strong believer in making shell scripts readable and testable with tools like bats-core.