mcpField
J
jo

jo

github.com/petr-korobeinikov開発167 回インストール2 週間前に更新
リポジトリ

jo について

シェルで引用符を手作業する代わりに、`jo` で JSON を組み立てる方法を扱うスキルです。値の型判定、ネスト構造、配列、ファイル入力、よく使うコマンド例を説明し、複雑な構文はマニュアルで確認するよう案内します。

主な機能

  1. 01シェルの値から JSON を生成
  2. 02JSON 値の型推定と強制指定
  3. 03ネストしたオブジェクトと配列の作成
  4. 04ファイル内容の読み込みと埋め込み
  5. 05既存 JSON ドキュメントの更新
  6. 06curl と kubectl の例

活用シーン

  1. 01シェル変数で API リクエスト本文を作る
  2. 02スクリプトでネストした JSON を生成する
  3. 03コマンドラインから Kubernetes リソースを変更する

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/petr-korobeinikov/skills --skill jo

インストール後、Claude Code で/joを入力して読み込まれたか確認します。

同梱ファイルreferences/options.md

詳細

jo

シェルスニペットで JSON を手作業で引用符付きのリテラルとして入力せずに、jo で組み立てます。 jo は JSON の引用符を内部で処理するため、 シェル変数をきれいに展開でき、 入れ子になったシングルクォートとダブルクォートを扱う必要がありません。

公式ドキュメント: https://github.com/jpmens/jo (README と jo.md の man ページ)。 重要な形式は、使用する前にマニュアルで確認してください。

理由

  • シェル文字列内に JSON を手書きすると、引用符のエスケープが非常に複雑になります。 '{"user":"x"}' に $VAR を挿入すると、シングルクォートが崩れるか、 読みにくく入力ミスもしやすい、ぎこちない '"$VAR"' の形式を使うことになります。
  • インライン JSON の入力ミス(カンマの抜け、余分な引用符、末尾のカンマ)は、 パース時ではなくサーバー側で失敗するため、 長い 1 行のペイロードでは見つけにくくなります。
  • jo は値から型を判定します。 数値、ブール値、null、ネストされたオブジェクト、配列を自動で検出します。 判定が不適切な場合(文字列のままにする必要がある数値 ID など)は、 単語ごとに -s/-n/-b で上書きできます。
  • jo は組み合わせて使えます。 シェル変数、コマンド置換、ブラケットパスの省略記法、ネストした jo 呼び出しを、 いずれも再エスケープせずに使えます。

jo による値の型判定

man ページによると、値の処理は次のとおりです。

  1. まず値を JSON としてパースします。 5 → 数値、 true/false → ブール値、 null → null、 {...}/[...] → 埋め込みオブジェクト/配列、 数値のように見えても有効な浮動小数点数ではない文字列 (例:3.14159.26)→ 文字列。
  2. JSON のパースに失敗した場合、 特殊な値のプレフィックスを確認します。 @file、%file、:file (下記の「ファイルからの読み込み」を参照)。
  3. **それ以外は、**リテラル文字列です。

値がない、または空の値(k=)は null になります。 リテラル文字列 true/false/null の検出を無効にするには、-B を渡します。 全体に適用される -n は、値が空のキーを削除します (-- の後に指定する単語ごとの型変換オプション -n とは別です)。

直接置換

使わない使う
'{"name":"alice"}'"$(jo name=alice)"
'{"name":"'"$USER"'"}'"$(jo name="$USER")"
'{"count":5,"active":true}'"$(jo count=5 active=true)"
'{"value":null}'"$(jo value=null)"(または "$(jo value=)")
'{"tags":["a","b","c"]}'"$(jo tags="$(jo -a a b c)")"
'{"point":[1,2]}'"$(jo 'point[]=1' 'point[]=2')"
'{"geo":{"lat":10,"lon":20}}'"$(jo 'geo[lat]=10' 'geo[lon]=20')"
'{"user":{"id":1,"name":"alice"}}'"$(jo user="$(jo id=1 name=alice)")"
'{"code":"12345"}'(文字列 ID)"$(jo -- -s code=12345)"

ブラケットパス形式(key[]=、key[sub]=)は1 階層のみです。 'a[b][c]=1' は [c] を黙って破棄し、{"a":{"b":1}} を生成します。 さらに深いネストには、コマンド置換を使って jo をネストしてください。

構文チートシート

値の形式
  • k=v — JSON としてパースし、次にプレフィックスを確認し、それ以外はリテラル文字列にします (「jo による値の型判定」を参照)。
  • k@v — 真偽値を表す値からブール値を生成します (T/t、またはゼロ以外の数値 → true、それ以外 → false)。 flag@$ENABLED のように使うと便利です。
  • k=@file — file の内容を文字列値として読み込みます。
  • k=%file — file を読み込み、Base64 エンコードされた文字列にします。
  • k=:file — file を JSON としてパースし、埋め込みます。
  • k:=file または k:=- — k=:file と同じですが、演算子として使います。 - は標準入力から JSON を読み込みます。

文字列値の先頭で @、%、または : をリテラルとして使うには、\ でエスケープします。 twitter='\@jpmens'、 vimcmd='\:split'、 uri='\\%20'。

ブラケットパス(1階層)
  • 'name[]=v1' 'name[]=v2' — name 配列に追加します。
  • 'obj[k]=v' — {"obj":{"k":v}} を作成します。
  • ドット記法には -d.(パス区切り文字)を組み合わせます。 jo -d. geo.lat=10 geo.lon=20 は jo 'geo[lat]=10' 'geo[lon]=20' と同等です。
  • ブラケット形式は必ず引用符で囲んでください。 引用符のない [ / ] は zsh のグロブ展開で処理されます (展開に一致するものがあれば、 bash でも同様です)。
配列
  • jo -a v1 v2 v3 — 自動的に型変換された値の配列を作成します。
  • jo -a -- -s 123 hello -n "five" — 配列内で単語ごとに型変換します (この例では ["123","hello",4] です。 数値以外の文字列に -n を指定すると、その長さになります)。
型変換
  • jo -- -s k=v — 文字列に強制変換します。 数値 ID、バージョン文字列、電話番号、郵便番号に使用します。
  • jo -- -n k=v — 数値に強制変換します (数値以外の文字列はその長さになります)。
  • jo -- -b k=v — ブール値に強制変換します (空の場合は false、それ以外は true です)。
  • 単語リストの先頭の単語が - で始まる場合は、 その前に -- が必須です。 マニュアルとの一貫性を保つため、常に指定してください。
グローバルオプション

最もよく使う 2 つのオプション:

  • -p — 整形して出力します (本番用のペイロードでは省略してください)。
  • -a — オブジェクトの代わりに配列を出力します。

オプションの全一覧 (-B、-D、グローバルな -n、-d sep、-f file、-e、-o、-v/-V、 および -- 以降の単語ごとの型変換の仕様)については、 references/options.md を参照してください。

イディオム

ボディ付きの curl POST:

curl -X POST https://api.example.com/v1/users \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d "$(jo name="$NAME" email="$EMAIL" active=true)"

1 階層のネストに使うブラケット形式の省略記法 (ネストした jo のコマンド置換は不要です):

curl -X POST https://api.example.com/v1/orders \
    -H "Authorization: Bearer $TOKEN" \
    -d "$(jo \
        'customer[id]='"$CUSTOMER_ID" \
        'customer[name]='"$CUSTOMER_NAME" \
        'items[]='"$SKU_A" \
        'items[]='"$SKU_B")"

1 階層より深いネスト — コマンド置換で構築します (または変数に格納します):

payload=$(jo \
    name="$NAME" \
    address="$(jo street="$STREET" city="$CITY")" \
    tags="$(jo -a admin user)")

curl -X POST -d "$payload" https://api.example.com/v1/users

kubectl のパッチ:

kubectl patch deployment web \
    --type=merge \
    --patch "$(jo spec="$(jo replicas=3)")"

文字列のままにする必要がある数値 ID (そうしないと jo は "id":12345 を数値として出力します):

curl -X POST -d "$(jo -- -s id=12345 name="$NAME")" \
    https://api.example.com/v1/users

既存の JSON ドキュメントを変更する:

curl -sSL https://api.example.com/v1/config \
    | jo -f - updated_at="$(date -Iseconds)" version="$NEW_VERSION"

jo を使用しない場合

大きな固定 JSON ドキュメント

長い jo の呼び出しを連ねるよりも、 リテラルの JSON を含むヒアドキュメントのほうが明確で、 API ドキュメントから JSON をそのままコピーして貼り付けられます:

curl -X POST -d @- https://api.example.com/v1/config <<'JSON'
{
  "feature_flags": {
    "alpha": true,
    "beta": false
  },
  "limits": {
    "rps": 100,
    "burst": 200
  }
}
JSON
ホストで jo を使用できない場合

最小構成の CI イメージや制限されたサーバーには、 jo がない場合があります。 ヒアドキュメントを代わりに使用してください。 壊れやすいインラインの引用符付き JSON を代わりに使用してはいけません。

jo のインストール

  • macOS:brew install jo または sudo port install jo
  • Debian/Ubuntu:apt install jo
  • Fedora:dnf install jo
  • Alpine:apk add jo
  • Gentoo:emerge jo
  • Arch:pacman -S jo(extra 内)
  • Snap:snap install jo
  • Windows:scoop install jo
  • Docker:docker run --rm jpmens/jo ...
  • ソースから: https://github.com/jpmens/jo

jo は aqua/mise のデフォルトの短縮名レジストリには含まれていません。 mise で管理されているホストでは、パッケージマネージャー経由、 または ubi:jpmens/jo 経由でインストールしてください。

対象範囲

シェルスニペットが JSON を出力する箇所すべてに適用されます:

  • Bash ツールの呼び出し。
  • SKILL.md / README.md / ドキュメント内のスニペット。
  • scripts/ 配下のスクリプト。
  • Makefile のレシピ。
  • CI 設定。
  • API のスモークテスト手順。

ファイルを編集する際に、手書きのインライン JSON 文字列を見つけた場合は、 同じ編集の一環として、同等の jo 形式に置き換えてください。

コメント