JSONを整形して眺めたり、構文が壊れていないか確認したり、ネストの奥にあるキーを探したり――そんな地味だけど頻発する作業を、Pythonのargparseだけで賄うCLIツールを実際に作りました。format・validate・searchの3コマンドに分けたことで、用途ごとに迷わず使える仕上がりになりました。
動画の内容をテキストで確認する
オープニング。argparseを使った実践内容を約34秒で紹介します。概要紹介。
この動画では、argparseでJSON整形・構文検証・キー検索CLIを作ります。具体的にやること。具体的には、3つのサブコマンドを分け、ネストしたキーを再帰検索します。
実装環境・必須アプリ。実装環境と必須アプリは、Windows 11 Pro / Python 3.13.3 / argparseです。実際のキャプチャ動画。
実際の画面で操作を確認します。検証の結果、CLIツールを4回のコマンドで実行し、全て正常(終了コード0)に動作しました。エンディング。
研修ならCodeCampで検索。
目次
- Pythonでargparseのコードを生成したプロンプトと作り方
- Python・argparseの環境構築(Windows 11/PowerShellで検証)
- Pythonのargparseで作るJSON CLIの方針
- Pythonでjson.loadsとargparseで実装するJSON整形・検証・キー検索
- Pythonで実行してみたJSON整形・検索CLIの結果
- Python argparse CLIでよくあるJSONエラーと対処
- Pythonの再帰検索で初心者がつまずきやすいポイント
- JSONPath風キー検索が使える場面
- Pythonで作るJSON CLIツールのまとめ
- 参考にした一次情報
Pythonでargparseのコードを生成したプロンプトと作り方
処理を3つのサブコマンドへ分けることで、入力方法と責務を明確にしています。JSON本文を直接渡す指定にすると、追加ファイルなしで同じ実行例を再現できます。
構文検証とキー検索の意味を分け、検索条件をキー名の完全一致に限定しました。再帰対象に辞書と配列の両方を明記することで、ネストしたJSONでも検索漏れを防ぎます。
生成プロンプトで工夫したポイント
-
サブコマンドはformat、validate、searchの3つにします。:この指定により、完成物の機能範囲と各処理の責務が明確になります。 -
任意の--strict時だけ不正JSONを終了コード1にしてください。:画面での検査と自動処理向けの終了コードを両立できる点が利点です。 -
dictとlistの全階層から再帰的に完全一致検索:ネスト構造と検索条件を具体化し、値検索との混同を防げます。
同じコードを作れる生成プロンプト(コピペ用・全文)
実際の生成時には、この記事のシステム都合の指定(図の保存先など)を少しだけ足していますが、以下はそのままコピペして同じものが作れるように整えた全文です。
Python・argparseの環境構築(Windows 11/PowerShellで検証)
この記事のセットアップ手順と掲載コードは、Windows 11 Pro、PowerShell 5.1、Python 3.13.3で動作確認しています。仮想環境を有効化せず、その中のPythonを直接指定するため、以下のコマンドはPowerShellとコマンドプロンプト(cmd)の両方で使えます。
python -m venv .venv
macOS・Linuxでは仮想環境内のPythonパスが異なります。今回の動作確認環境とは異なるため、以下は環境差分を補う参考手順です。
python3 -m venv .venv
- 追加パッケージは不要で、Python標準ライブラリだけで動作します。
Pythonのargparseで作るJSON CLIの方針
この記事では、Pythonのargparseを使ってJSONを整形・検証・キー検索できるコマンドラインツールを実際に作ります。
方針はシンプルで、format・validate・searchという3つの処理をargparseのサブパーサーで分離し、それぞれ独立したコマンドとして扱うことにしました。
入力されたJSON文字列はjson.loadsで解析し、キー検索だけは辞書とリストをたどる再帰関数にまとめて、見つかった位置をJSONPath風の表記で表示する設計にしています。
このセクションの用語
- サブパーサー
- 1つのCLIの中に
formatやsearchのような複数のサブコマンドを定義するためのargparseの仕組みです。 - JSONPath風表記
-
$.user.nameのように、JSON内のどの位置にある値かを.や[]で示す簡易的な表記方法です。
参考:
©Python公式ドキュメント(argparse)argparse supports the creation of such sub-commands with the add_subparsers() method.
Pythonでjson.loadsとargparseで実装するJSON整形・検証・キー検索
実装は4つの処理を素直に関数へ分けただけのシンプルな構成です。command_format・command_validate・command_searchという3つのハンドラ関数と、キー検索用のfind_key関数を用意しました。
各ハンドラはargs.jsonをjson.loadsで解析し、失敗するとjson.JSONDecodeErrorを捕まえてエラー内容と行・列番号を表示します。
最後にbuild_parser関数がargparse.ArgumentParserとadd_subparsersでコマンドラインの入り口を組み立てる役割です。
このセクションの用語
- JSONDecodeError
-
json.loadsに渡した文字列がJSONとして不正な形式だったときにPythonが送出する例外です。 - 再帰関数
- 自分自身を呼び出しながら、ネストした辞書やリストの奥まで処理を繰り返す関数のことです。
# -*- coding: utf-8 -*-
"""JSON整形・構文検証・キー検索だけを扱うargparse製CLI。"""
from __future__ import annotations
import argparse
import json
from typing import Any
# JSONの整形
def command_format(args: argparse.Namespace) -> int:
try:
data = json.loads(args.json)
except json.JSONDecodeError as exc:
print(f"INVALID: {exc.msg} (line {exc.lineno}, column {exc.colno})")
return 1
print(json.dumps(data, ensure_ascii=False, indent=2, sort_keys=True))
return 0
# JSON構文の検証
def command_validate(args: argparse.Namespace) -> int:
try:
json.loads(args.json)
except json.JSONDecodeError as exc:
print(f"INVALID: {exc.msg} (line {exc.lineno}, column {exc.colno})")
return 1 if args.strict else 0
print("VALID: JSON構文に問題はありません。")
return 0
# ネストしたキーの再帰検索
def find_key(node: Any, target_key: str, path: str = "$") -> list[tuple[str, Any]]:
matches: list[tuple[str, Any]] = []
if isinstance(node, dict):
for key, value in node.items():
child_path = f"{path}.{key}"
if key == target_key:
matches.append((child_path, value))
matches.extend(find_key(value, target_key, child_path))
elif isinstance(node, list):
for index, value in enumerate(node):
matches.extend(find_key(value, target_key, f"{path}[{index}]"))
return matches
def command_search(args: argparse.Namespace) -> int:
try:
data = json.loads(args.json)
except json.JSONDecodeError as exc:
print(f"INVALID: {exc.msg} (line {exc.lineno}, column {exc.colno})")
return 1
matches = find_key(data, args.key)
print(f"FOUND: {len(matches)}件")
for path, value in matches:
rendered = json.dumps(value, ensure_ascii=False, separators=(",", ":"))
print(f"{path} = {rendered}")
return 0
# argparseのサブコマンド定義
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="JSONの整形・構文検証・キー検索を行うCLIです。")
subcommands = parser.add_subparsers(dest="command", required=True)
format_parser = subcommands.add_parser("format", help="JSONを読みやすく整形します。")
format_parser.add_argument("--json", required=True, help="整形するJSON本文")
format_parser.set_defaults(handler=command_format)
validate_parser = subcommands.add_parser("validate", help="JSON構文を検証します。")
validate_parser.add_argument("--json", required=True, help="検証するJSON本文")
validate_parser.add_argument(
"--strict", action="store_true",
help="INVALIDの場合に終了コード1を返します。")
validate_parser.set_defaults(handler=command_validate)
search_parser = subcommands.add_parser("search", help="キー名を再帰検索します。")
search_parser.add_argument("--json", required=True, help="検索するJSON本文")
search_parser.add_argument("--key", required=True, help="完全一致で探すキー名")
search_parser.set_defaults(handler=command_search)
return parser
def main() -> int:
args = build_parser().parse_args()
return int(args.handler(args))
if __name__ == "__main__":
raise SystemExit(main())
コード全文は上の折り畳みに入れてあるので、全部を上から読む必要はありません。ここでは特に重要な部分だけを抜き出して、何をしているのか順番に見ていきます。
command_format関数でJSONを整形する
def command_format(args: argparse.Namespace) -> int:
try:
data = json.loads(args.json)
except json.JSONDecodeError as exc:
print(f"INVALID: {exc.msg} (line {exc.lineno}, column {exc.colno})")
return 1
print(json.dumps(data, ensure_ascii=False, indent=2, sort_keys=True))
return 0--jsonで渡された文字列をjson.loadsでPythonのオブジェクトに変換し、json.dumpsでインデント付き・キーのソート済みの読みやすい形式に整形します。解析に失敗した場合は、終了コード1を返す仕様です。
json.JSONDecodeErrorで構文エラーを捕捉する
except json.JSONDecodeError as exc:
print(f"INVALID: {exc.msg} (line {exc.lineno}, column {exc.colno})")
return 13つのハンドラすべてで同じパターンを使い、exc.msg・exc.lineno・exc.colnoからエラーメッセージと発生位置を表示する仕組みです。どこが壊れているJSONなのか特定しやすくなります。
command_validate関数と--strictオプション
def command_validate(args: argparse.Namespace) -> int:
try:
json.loads(args.json)
except json.JSONDecodeError as exc:
print(f"INVALID: {exc.msg} (line {exc.lineno}, column {exc.colno})")
return 1 if args.strict else 0
print("VALID: JSON構文に問題はありません。")
return 0構文検証だけを行うコマンドです。--strictが指定されていれば不正なJSONのときに終了コード1を返し、指定がなければ0のままメッセージだけ表示するという挙動の切り替えができます。
find_key関数でネストしたキーを再帰的にたどる
def find_key(node: Any, target_key: str, path: str = "$") -> list[tuple[str, Any]]:
matches: list[tuple[str, Any]] = []
if isinstance(node, dict):
for key, value in node.items():
child_path = f"{path}.{key}"
if key == target_key:
matches.append((child_path, value))
matches.extend(find_key(value, target_key, child_path))辞書ならキーと値を1つずつ確認し、目的のキーと一致すれば現在位置を記録します。値がさらに辞書やリストであればfind_key自身を再度呼び出し、ネストの奥まで探索を続ける仕組みです。
リスト要素をたどるインデックス付きパス
elif isinstance(node, list):
for index, value in enumerate(node):
matches.extend(find_key(value, target_key, f"{path}[{index}]"))
return matches対象がリストの場合はenumerateで要素番号を取り出し、[0]のようにインデックス付きのパス文字列を組み立てながら再帰します。この処理によって、リスト内の辞書にもキー検索が届くようになりました。
build_parserとサブパーサーでコマンドを分離
subcommands = parser.add_subparsers(dest="command", required=True)
format_parser = subcommands.add_parser("format", help="JSONを読みやすく整形します。")
format_parser.add_argument("--json", required=True, help="整形するJSON本文")
format_parser.set_defaults(handler=command_format)add_subparsersでformat・validate・searchのサブコマンドを追加し、それぞれに--json引数と対応するハンドラ関数をset_defaultsで紐づけます。コマンド名ごとに処理が完全に分かれるのがこの設計の利点です。
Pythonで実行してみたJSON整形・検索CLIの結果
実際にこのCLIツールをコマンドラインから4回実行し、format・validate・searchそれぞれの動作を確認しました。
4回の実行はすべて正常に完了し、終了コードは全て0でした。エラーメッセージが出るケースも試しましたが、想定通りINVALID表示と対応する終了コードが返ってきました。
画像として、実際にコマンドを打ち込んで結果が表示されるまでの実行セッションのキャプチャを残しています。
このセクションの用語
- 終了コード
- コマンドの実行結果を表す数値で、
0は正常終了、1などの非ゼロ値は何らかのエラーがあったことを示します。

Python argparse CLIでよくあるJSONエラーと対処
argparseを使ったCLIツールでは、JSON自体の構文ミスとコマンドライン引数の指定ミスの両方でエラーが起きやすくなります。
代表的なパターンを事前に知っておくと、実行時に慌てずに対処できます。
| エラー例 | 原因 | 対処 |
|---|---|---|
| INVALID: Expecting value (line 1, column 1) |
--jsonに空文字や壊れたJSONを渡した |
JSON文字列全体をクォートで囲み、構文が閉じているか再確認する |
| error: the following arguments are required: --json |
--jsonオプションを付け忘れた |
コマンドに--json '...'の形で本文を追加する |
| error: argument command: invalid choice |
format/validate/searchのスペルミスや未定義のサブコマンド指定 |
-hオプションでサブコマンド名の一覧を確認する |
| シェル側でJSONの引用符が崩れて解析に失敗する | PowerShellやbashでJSON文字列のクォートの扱いを誤った | JSON全体をシングルクォートで囲むか、ファイルから読み込む方式に変える |
| FOUND: 0件と表示される | 検索したいキー名のタイプミスやネスト構造の勘違い | 先にformatで整形結果を確認してからキー名を見直す |
Pythonの再帰検索で初心者がつまずきやすいポイント
find_keyのような再帰関数は、一度理解してしまえば単純な処理ですが、最初はどこで止まるのか掴みにくいところです。
find_keyは辞書でもリストでもない値(文字列や数値)に到達すると何もせずmatchesを返すだけなので、無限に再帰し続ける心配はありません。
検索対象のキー名は完全一致でしか見つからないため、大文字・小文字の違いやタイプミスがあるとFOUND: 0件になります。原因を調べるには、formatで構造を確認するのが近道です。
同じキー名がJSON内に複数存在する場合、find_keyは最初の1件だけでなく見つかったすべての位置を返します。件数が多いときは出力が長くなる点に注意してください。
PowerShellやbashでJSON文字列を--jsonに渡すときは、引用符の扱いを誤るとシェル側でJSONが崩れてしまいます。JSON全体を1つの文字列としてクォートで囲むことを意識してください。
JSONPath風キー検索が使える場面
searchサブコマンドはキー名を指定するだけで、ネストの深さに関係なく該当箇所を洗い出せるため、実務のちょっとした調査に応用しやすい機能です。
| 使える場面 | 具体的な使い方 |
|---|---|
| APIレスポンスの目視確認 | curlなどで取得したJSONをformatサブコマンドに渡し、インデント付きで読みやすく整形してから中身を確認する |
| 設定ファイルの構文チェック | デプロイ前にvalidateサブコマンドをスクリプトへ組み込み、--strict付きでJSON構文が壊れていないか自動チェックする |
| 大きくネストしたJSONからの値抽出 | 設定ファイルや複雑なレスポンスに対してsearchサブコマンドでキー名を指定し、該当箇所をJSONPath風の位置情報付きで洗い出す |
Pythonで作るJSON CLIツールのまとめ
argparseのサブパーサーでformat・validate・searchを分離し、json.loadsと再帰関数のfind_keyを組み合わせるだけで、実用的なJSON操作CLIを作れることを確認しました。
4回の実行はいずれも終了コード0で完了しており、整形・構文検証・キー検索の基本機能がひと通り動作します。
エラー位置や検索結果のパスも確認できるため、JSON処理の仕組みを理解しやすい題材です。
さらに詳しく学べるPython研修の詳細はこちら参考にした一次情報
- ^ argparse — Parser for command-line options, arguments and sub-commands. https://docs.python.org/3/library/argparse.html, (参照26-07-15).
- ^ json — JSON encoder and decoder. https://docs.python.org/3/library/json.html, (参照26-07-15).
※内容は執筆時点のものです。ライブラリやサイトの仕様は変わる可能性があるため、公式ドキュメントもあわせてご確認ください。
ITやプログラミングに関するコラム
【CSS】notで複数の件を除外する方法
【Git】remote設定を変更する方法
【VBA】コメントアウトを設定する方法
x86とx64の違いを分かりやすく解説
マークダウンで改行する方法
CapsLockキーを解除する方法
GitLabとGitHubの違いを解説
Linuxで環境変数を確認する方法
UbuntuのIPアドレスを確認する方法
パソコンのメモリの目安を用途別に選ぶ方法
ITやプログラミングに関するニュース
VercelがAI GatewayにSeedream 5.0 Proを追加、AI SDKのモデル指定で画像生成と編集が可能に
AWSがAmazon LocationのPlaces APIを強化、住所表記の指定と移動手段別の検索が可能に
VercelがトレースにTree・Waterfallビューを追加、ログ画面で処理の階層と所要時間を確認可能に
Googleがエージェント評価の再考を提唱、難易度を情報量で測るDiscovery Benchを解説
Google CloudがCloud Runサンドボックスを公開プレビューで提供、サービスヘルスは一般提供に
Google Cloud EMEAが英国金融の重要第三者に指定、イングランド銀行・PRA・FCAの直接監督下に
AWS DMS Schema ConversionがSQL Serverのオフライン変換に対応、ソースDBへ接続せずスキーマを変換可能に
EC2 G7インスタンスが米国東部(バージニア北部)で利用可能に、G6比でAI推論性能が最大4.6倍
SageMaker HyperPodが継続プロビジョニングでのAMIベース構成に対応、S3のスクリプト管理なしでSlurmクラスターを作成可能に
AWSがEMR on EKSでSparkトラブルシューティングエージェントに対応、失敗ジョブの原因分析を自然言語で依頼可能に
