API連携に必須!curlでJSONをPOSTする実践テクニック

はい、承知いたしました。API連携に必須である curl コマンドを用いたJSONデータのPOST送信に関する詳細な解説記事を、約5000語で記述します。


API連携に必須!curlでJSONをPOSTする実践テクニック – 詳細解説

はじめに:なぜAPI連携とcurl、そしてJSONなのか?

現代のシステム開発において、API(Application Programming Interface)連携は不可欠な要素となっています。異なるシステム間でデータをやり取りし、機能を連携させることで、より複雑で強力なアプリケーションを構築することが可能になります。Webサービスの連携、マイクロサービスの通信、モバイルアプリケーションのバックエンド連携など、その用途は多岐にわたります。

API連携の主要な手段の一つが、HTTPプロトコルを介したデータ交換です。特に、クライアントがサーバーに対してデータを送信する際には、HTTPのPOSTメソッドが頻繁に利用されます。そして、その送信されるデータの形式として、JSON(JavaScript Object Notation)はデファクトスタンダードと言えるほど広く普及しています。軽量で人間が読み書きしやすく、多くのプログラミング言語で容易に扱えるため、構造化されたデータをAPIでやり取りするのに最適なのです。

このようなAPI連携の現場において、開発者やエンジニアにとって強力な味方となるのが curl コマンドです。curl は、URL構文を用いてデータを転送するためのコマンドラインツールであり、HTTP, HTTPS, FTPなど様々なプロトコルをサポートしています。特に、API連携のテスト、デバッグ、あるいは簡単なバッチ処理やスクリプト内でのAPI呼び出しにおいて、curl はその手軽さと柔軟性から絶大な威力を発揮します。

ブラウザや専用のGUIツール(Postman, Insomniaなど)もAPI操作には便利ですが、curl には以下のような利点があります。

  • 環境を選ばない: ほとんどのOS(Linux, macOS, Windows)に標準搭載または容易にインストール可能。
  • 軽量: 起動が速く、リソース消費が少ない。
  • スクリプト親和性: シェルスクリプトやバッチファイルに組み込みやすい。
  • 自動化: 定期的なタスクやCI/CDパイプラインでのAPI呼び出しに利用可能。
  • 詳細な制御: ヘッダー、認証、タイムアウトなど、HTTPリクエストのあらゆる側面を細かく制御できる。
  • デバッグ: -v オプションなどで通信の詳細を確認しやすく、問題特定に役立つ。

この記事では、curl を使ってJSONデータをHTTP POSTリクエストとして送信する、API連携における最も基本的かつ重要なテクニックに焦点を当て、その詳細を徹底的に解説します。単にコマンドの書き方を説明するだけでなく、なぜそのオプションが必要なのか、どのような挙動をするのか、よくある落とし穴や解決策、さらには実践的なシナリオでの応用方法まで、網羅的にカバーします。

この記事を読み終える頃には、あなたは curl を使って自信を持ってJSON POSTリクエストを操り、API連携の様々な場面でそのスキルを活かせるようになっているでしょう。

curlの基本とHTTP POSTリクエストの構造

JSON POSTの詳細に入る前に、curlの基本的な使い方と、HTTP POSTリクエストがどのような構造になっているかを確認しておきましょう。

curlコマンドの基本的な使い方

curlコマンドの基本的な構文は以下のようになります。

bash
curl [オプション...] <URL>

最も単純な例は、GETリクエストで特定のURLからコンテンツを取得することです。

bash
curl https://example.com

これにより、指定したURLのウェブページのHTMLソースが表示されます。

HTTPメソッドの種類とPOSTの役割

HTTPプロトコルでは、クライアントがサーバーに対してどのような操作を行いたいかを指示するために「メソッド」を使用します。主なメソッドには以下のようなものがあります。

  • GET: 指定したリソースの表現を取得します。データの取得に用いられ、リクエストボディは通常伴いません。
  • POST: 指定したリソースにデータを送信し、そのリソースに対する処理を要求します。新しいリソースの作成や、フォームデータの送信などに使われます。JSONデータをAPIに送信する際の主要なメソッドです。
  • PUT: 指定したURIにリクエストボディを保存します。既存リソースの更新や、新しいリソースの作成に使われます(クライアントがURIを指定する場合)。
  • DELETE: 指定したリソースを削除します。
  • PATCH: リソースの部分的な更新を行います。

API連携において、クライアントがサーバーにデータを送信して新しいレコードを作成したり、既存レコードを更新したり、あるいは特定の処理をトリガーしたりする場合に、POSTメソッドが最もよく利用されます。

HTTP POSTリクエストの構造

HTTP POSTリクエストは、大きく分けて以下の要素で構成されます。

  1. リクエストライン: メソッド(POST)、パス、HTTPバージョンなどが含まれます。
    POST /api/users HTTP/1.1
  2. ヘッダー: リクエストに関する様々なメタデータを提供します。例えば、送信するデータの種類(Content-Type)、認証情報(Authorization)、クライアントの情報(User-Agent)などが含まれます。各ヘッダーは Header-Name: Header-Value の形式で記述されます。
    Host: api.example.com
    Content-Type: application/json
    Content-Length: 123
    Authorization: Bearer your_token
  3. リクエストボディ: サーバーに送信したい実際のデータが含まれます。POSTリクエストの最も重要な部分であり、JSONデータはこの部分に格納されます。

curl を使ってPOSTリクエストを送信する場合、デフォルトではGETリクエストになるため、-X POST オプションを使って明示的にメソッドを指定する必要があります。ただし、後述する-d--data といったオプションを使う場合は、curl は自動的にメソッドをPOSTに設定するため、-X POST は省略可能です。しかし、明示性を高めるために -X POST を付けることも推奨されます。

JSONデータの準備

curlでPOSTするJSONデータは、通常、文字列としてコマンドラインに直接記述するか、ファイルに保存しておき、それをcurlに読み込ませる方法があります。どちらの方法を選択するかは、JSONデータのサイズ、複雑さ、再利用性の必要性によって判断します。

JSONフォーマットの基本

JSONは、キーと値のペアの集まり(オブジェクト {})や、値の順序付きリスト(配列 [])で構成されます。値としては、文字列、数値、真偽値(true/false)、null、オブジェクト、配列が使用可能です。

例:シンプルなユーザーオブジェクト

json
{
"username": "tech-user",
"email": "[email protected]",
"isActive": true,
"roles": ["reader", "writer"]
}

このJSONデータをcurlで送信可能な形式で準備する必要があります。

JSONデータを文字列として準備する

コマンドラインに直接記述する場合、JSON文字列全体をシングルクォートまたはダブルクォートで囲みます。JSON内部でクォートが必要な場合は、外側のクォートの種類に合わせてエスケープする必要があります。

  • シングルクォートで囲む場合: JSON内部のダブルクォート " はそのまま記述できます。JSON内部にシングルクォート ' が含まれる場合は、\' のようにエスケープが必要ですが、JSONではキーや文字列リテラルにシングルクォートは通常使用しないため、このケースは稀です。
  • ダブルクォートで囲む場合: JSON内部のダブルクォート "\" のようにバックスラッシュでエスケープする必要があります。JSON内部にバックスラッシュ \ が含まれる場合も \\ とエスケープが必要です。

例:シングルクォートで囲む

json
'{ "name": "John Doe", "age": 30 }'

例:ダブルクォートで囲む(内部のダブルクォートをエスケープ)

json
"{ \"name\": \"John Doe\", \"age\": 30 }"

一般的に、JSON文字列は内部にダブルクォートを多用するため、外側をシングルクォートで囲む方法がシェルでのエスケープが少なくて済むため、より推奨されます。ただし、シェルによってはシングルクォート内のバックスラッシュの扱いが異なる場合があるため、注意が必要です。

JSONデータをファイルとして準備する

より複雑なJSONデータや、何度も同じデータを送信する場合、JSONデータを.jsonなどの拡張子を持つテキストファイルに保存するのが効率的です。

例:data.jsonというファイルにJSONを保存

json
{
"product_id": "A123",
"name": "Laptop",
"price": 1200.00,
"tags": ["electronics", "computer", "portable"]
}

この方法の利点は、JSONデータ自体をシェルから独立して管理できるため、エスケープの問題が解消され、可読性が高まることです。

curlでJSONをPOSTする基本

いよいよcurlを使ってJSONデータをPOST送信する方法を具体的に見ていきましょう。主要なオプションは -X POST-H、そして -d または --data です。

Content-Type: application/json ヘッダーの重要性

APIにJSONデータを送信する際、最も重要なヘッダーの一つが Content-Type です。これは、リクエストボディに含まれるデータの形式をサーバーに伝える役割を果たします。JSONデータを送信する場合は、必ず Content-Type: application/json を指定する必要があります。サーバーはこのヘッダーを見て、受信したリクエストボディをJSONとしてパースしようとします。このヘッダーを付け忘れると、サーバーはリクエストボディを正しい形式で解釈できず、エラーになる可能性が高いです。

curlでヘッダーを指定するには、-H オプションを使用します。

bash
-H "Content-Type: application/json"

-H オプションは複数指定できるため、他のヘッダー(認証情報など)も同時に指定できます。

bash
-H "Content-Type: application/json" -H "Authorization: Bearer your_token"

リクエストボディを送信する -d / --data オプション

curlでリクエストボディを含めてPOSTリクエストを送信するには、-d または --data オプションを使用します。これらのオプションは、指定されたデータをリクエストボディとして含め、さらに以下の処理を自動的に行います。

  1. HTTPメソッドをPOSTに設定します(-X POST は省略可能になりますが、明示のため付けても構いません)。
  2. リクエストヘッダーに Content-Type: application/x-www-form-urlencoded を追加します。

注: -d--data を使うと、デフォルトで application/x-www-form-urlencoded が付加されます。JSONを送信する場合は、このデフォルトの Content-Typeapplication/json で上書きする 必要があります。したがって、JSON POSTでは -d-H "Content-Type: application/json" はセットで使うのが基本となります。

-d オプションには、送信したいデータを文字列として直接渡すか、ファイルから読み込むかを指定できます。

簡単なJSONデータを直接 -d で送信する例

最も基本的なJSON POSTの例です。JSONデータを文字列として -d オプションに渡します。

bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{"id": 101, "status": "active"}' \
https://api.example.com/items

解説:
* -X POST: HTTPメソッドとしてPOSTを明示的に指定します(-dを使う場合は省略可能ですが、推奨)。
* -H "Content-Type: application/json": リクエストボディのデータ形式がJSONであることをサーバーに伝えます。これがJSON POSTには必須です。
* -d '{"id": 101, "status": "active"}': リクエストボディとして送信するJSONデータを指定します。ここではシングルクォートで囲んでおり、JSON内部のダブルクォートはそのままです。
* https://api.example.com/items: リクエストの送信先URLです。

このコマンドは、指定したURLに対してJSONデータを含むPOSTリクエストを送信します。

ファイルからJSONデータを読み込んで -d で送信する例 (@filename)

前述のように、JSONデータが複雑な場合やファイルとして管理したい場合は、-d オプションに @ 記号とファイル名を続けて指定することで、ファイルの内容をリクエストボディとして読み込ませることができます。

まず、JSONデータをファイルに保存します。例:request_body.json

json
{
"name": "New Product",
"description": "This is a description of the new product.",
"price": 99.99,
"is_available": true,
"attributes": {
"color": "red",
"size": "M"
},
"tags": ["new", "featured", "sale"]
}

そして、curlコマンドでこのファイルを指定します。

bash
curl -X POST \
-H "Content-Type: application/json" \
-d @request_body.json \
https://api.example.com/products

解説:
* -d @request_body.json: request_body.json ファイルの内容を読み込み、それをリクエストボディとして送信します。この方法を使えば、ファイル内のJSONデータにシェルによるエスケープは不要です。

この方法は、JSONデータが大きくなったり、特殊文字(シェルにとって意味を持つ文字)を含む場合に特に有効です。

実践テクニック:複雑なJSONデータとファイルからの送信

JSONデータが複雑になったり、動的に生成される場合、シェルからの直接入力には限界が出てきます。ここでは、より実践的なJSONデータの扱い方と、-d 以外の関連オプションについて解説します。

エスケープ処理の必要性と <<EOF (ヒアドキュメント)

JSON文字列を直接-dに渡す場合、JSON内部の文字がシェルにとって特別な意味を持つ文字(例えば $, ``,`, " など)である場合、適切にエスケープしないと予期せぬエラーや挙動を引き起こす可能性があります。

例:JSON内にシェルの変数展開に使われる可能性がある文字を含む場合

json
{
"message": "Hello $user!",
"path": "C:\\temp\\data"
}

これをシングルクォートで囲む場合、$ はシェルによって変数展開されようとする可能性があります。ダブルクォートで囲む場合は $\ をエスケープする必要があります。

“`bash

シェルによって $user が展開される可能性がある

curl -X POST -H “Content-Type: application/json” -d ‘{“message”: “Hello $user!”, “path”: “C:\temp\data”}’ https://api.example.com/send

ダブルクォートで囲む場合は $ と \ をエスケープ

curl -X POST -H “Content-Type: application/json” -d “{\”message\”: \”Hello \$user!\”, \”path\”: \”C:\\temp\\data\”}” https://api.example.com/send
“`

このようなエスケープの複雑さを避けるために、以下の方法がよく使われます。

  1. ファイルに保存 (-d @filename): 最も推奨される方法。ファイルの内容はシェルに解釈されないため、エスケープは不要です。
  2. ヒアドキュメント (<<EOF): シェルスクリプト内で複数行の文字列を扱う際に便利な機能です。ヒアドキュメントを使うと、複数行のJSONデータをエスケープなし(または最小限のエスケープ)で curl に渡すことができます。

ヒアドキュメントを使った例:

“`bash
read -r -d ” json_data << EOF
{
“message”: “Hello $user! This is a multi-line message.”,
“data”: [
1,
2,
3
],
“settings”: {
“enabled”: true,
“limit”: 100
}
}
EOF

ここで $user 変数はシェルによって展開されますが、json_data 変数全体がシェルに解釈されるのを防ぐために ‘EOF’ をクォートすることもできます。

read -r -d ” json_data << ‘EOF’ # こちらの場合、$user はそのまま文字列として保持されます。

curl -X POST \
-H “Content-Type: application/json” \
-d “$json_data” \
https://api.example.com/process
“`

解説:
* read -r -d '' json_data << EOF ... EOF: ヒアドキュメントを使って、複数行のテキストを json_data という変数に格納します。
* read -r: バックスラッシュによるエスケープを無効にします。
* -d '': 区切り文字を空文字列に設定し、入力の最後まで(ここでは EOF マーカーまで)を読み込みます。
* << EOF: ヒアドキュメントの開始を示し、デリミタとして EOF を使用します。続く行が EOF だけの行が現れるまで json_data 変数に読み込まれます。
* << 'EOF': デリミタをシングルクォートで囲むと、ヒアドキュメント内の変数展開やコマンド置換が無効になります。JSONデータにシェルの特殊文字が含まれていても、そのままの文字列として扱いたい場合にこちらを使います。
* -d "$json_data": 変数に格納されたJSONデータを -d オプションに渡します。変数をダブルクォートで囲むことで、変数内の改行などが保持されます。

ヒアドキュメントはシェルスクリプト内で動的にJSONを生成したり、長いJSONを手作業で入力する場合に便利ですが、ファイルを使う方法に比べるとやや記述が複雑になります。

--data-binary / --data-raw オプション

-d / --data オプションは、デフォルトでデータをURLエンコードし、Content-Type: application/x-www-form-urlencoded をセットします。しかし、JSONデータはURLエンコードする必要がなく、また application/json ヘッダーが必要です。前述の例では -H "Content-Type: application/json" で上書きしていますが、-d のデフォルト挙動は少し不自然です。

curlには、リクエストボディの扱い方をより細かく制御するためのオプションがあります。

  • --data-binary: 指定されたデータをバイナリとして、つまり一切変更せずに(URLエンコードせずに)リクエストボディとして送信します。-d と同様に、-X POST を自動的に設定しますが、Content-Type は自動で設定しません。JSONデータを送信する際に、エスケープなどの変換をされたくない場合に適しています。
  • --data-raw: --data-binary と似ていますが、入力の先頭にある @ を特別扱いせず、単なる文字列として扱います。こちらもURLエンコードせず、Content-Type も自動設定しません。

JSON POSTにおいては、-d-H "Content-Type: application/json" を組み合わせる方法が最も一般的で広く使われています。しかし、データの変更(特に改行や特殊文字の扱い)を防ぎたい場合は --data-binary の方がより意図に合っていると言えます。

--data-binary を使った例:

bash
curl -X POST \
-H "Content-Type: application/json" \
--data-binary @request_body.json \
https://api.example.com/products

bash
curl -X POST \
-H "Content-Type: application/json" \
--data-binary '{"message": "Hello\nWorld!"}' \
https://api.example.com/greet

この例では、\n がそのままリクエストボディに含まれます。-d の場合はシェルやcurlの処理によっては \n が実際の改行文字に変換される可能性があります。

--data-raw を使った例:

“`bash

“@file.json” という文字列自体をリクエストボディとして送りたい場合(通常は稀)

curl -X POST \
-H “Content-Type: application/json” \
–data-raw ‘@file.json’ \
https://api.example.com/raw_data
“`

JSON POSTにおいては、ほとんどの場合 -d @filename-d '...' + -H "Content-Type: application/json" の組み合わせで十分です。ただし、バイナリデータ(例えばBase64エンコードされた画像データなど)をJSON内に含めて送信するような、より厳密なデータ転送が必要な場合は --data-binary が有効な選択肢となります。

API連携に必須の追加オプション

実際のAPI連携では、単にJSONをPOSTするだけでなく、認証、エラーハンドリング、デバッグ、ネットワーク設定など、様々な要素を考慮する必要があります。curlはこれらの要件を満たすための豊富なオプションを提供しています。

ヘッダーの操作 (-H を複数回使う)

APIは、Content-Type 以外にも様々なヘッダーを要求することがあります。認証情報 (Authorization)、APIキー、リクエストの追跡ID (X-Request-ID)、ユーザーエージェント (User-Agent) などです。これらのヘッダーはすべて -H オプションを繰り返して指定します。

bash
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_access_token" \
-H "X-Correlation-ID: abc-123-xyz" \
-d '{"action": "process", "data": {"value": 123}}' \
https://api.example.com/process_data

不要なヘッダーを削除したい場合は、ヘッダー名にコロンだけを付けて指定します。例えば、デフォルトで送られる可能性のある Accept: ヘッダーを削除したい場合などです。

bash
curl -H "Accept:" ... # Accept ヘッダーを送信しない

認証オプション

多くのAPIは、リクエストを行ったクライアントを識別し、権限をチェックするために認証を要求します。curl は様々な認証方法をサポートしています。

  • Basic認証 (-u, --user): ユーザー名とパスワードを username:password の形式でBase64エンコードして Authorization: Basic ... ヘッダーとして送信します。

    bash
    curl -X POST \
    -H "Content-Type: application/json" \
    -u "myuser:mypassword" \
    -d '{"message": "secure data"}' \
    https://api.example.com/secure/data

    パスワードをコマンドラインに平文で書きたくない場合は、パスワード部分を省略すると curl が実行時に入力プロンプトを表示します。

    bash
    curl -u "myuser:" ... # 実行時にパスワード入力が求められる

  • Bearerトークン (OAuth 2.0などで一般的): Authorization: Bearer <token> ヘッダーとしてトークンを送信します。これはカスタムヘッダーとして -H で指定します。

    bash
    ACCESS_TOKEN="your_actual_access_token"
    curl -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    -d '{"action": "do_something"}' \
    https://api.example.com/resource

  • APIキー: APIキーは、カスタムヘッダーとして送信されることもあれば、クエリパラメータとして送信されることもあります。仕様に合わせて -H または URL に直接記述して指定します。

    “`bash

    ヘッダーとして送信する場合

    curl -X POST \
    -H “Content-Type: application/json” \
    -H “X-API-Key: YOUR_API_KEY” \
    -d ‘{“data”: “payload”}’ \
    https://api.example.com/service

    クエリパラメータとして送信する場合

    curl -X POST \
    -H “Content-Type: application/json” \
    -d ‘{“data”: “payload”}’ \
    “https://api.example.com/service?api_key=YOUR_API_KEY”
    “`

タイムアウトと接続設定

APIが応答しない場合や遅延している場合に、curlがいつまで待つかを制御できます。スクリプトなどでAPIを呼び出す場合に、無限に待機するのを防ぐために重要です。

  • --connect-timeout <seconds>: TCP接続が確立されるまでの最大時間を指定します。
  • -m <seconds>, --max-time <seconds>: リクエスト全体(接続、データ送信、レスポンス受信)にかかる最大時間を指定します。この時間を超えると、curlは処理を中断します。

“`bash

接続試行は10秒まで、リクエスト全体は30秒まで待つ

curl -X POST \
–connect-timeout 10 \
-m 30 \
-H “Content-Type: application/json” \
-d ‘{“key”: “value”}’ \
https://api.example.com/slow_endpoint
“`

  • --retry <num>: 一時的なエラー(例: 5xx系ステータスコード)が発生した場合に、指定された回数だけリクエストを再試行します。

    “`bash

    最大3回再試行する

    curl –retry 3 …
    “`

進捗表示と詳細出力 (-v, -i, -s)

APIの挙動を確認したり、デバッグしたりする際に、curlの出力オプションは非常に役立ちます。

  • -v, --verbose: リクエストとレスポンスの詳細な情報を表示します。送信しているヘッダー、受信したヘッダー、接続情報などがstderrに出力されます。デバッグ時にはほぼ必須のオプションです。

    bash
    curl -X POST \
    -v \
    -H "Content-Type: application/json" \
    -d '{"test": true}' \
    https://api.example.com/debug

    出力例(一部):
    “`
    * Added api.example.com:443:XX.XX.XX.XX to DNS cache
    * About to connect() to api.example.com port 443 (#0)
    * Trying XX.XX.XX.XX…
    * Connected to api.example.com (XX.XX.XX.XX) port 443 (#0)

    POST /debug HTTP/1.1
    Host: api.example.com
    User-Agent: curl/7.54.0
    Accept: /
    Content-Type: application/json
    Content-Length: 14

    • upload completely sent off: 14 out of 14 bytes
      < HTTP/1.1 200 OK
      < Content-Type: application/json
      < Date: Mon, 23 Oct 2023 10:00:00 GMT
      < Content-Length: 25
      <
    • Connection #0 to host api.example.com left intact
      {“status”: “success”, “data”: {}} # <= レスポンスボディ
      “`
  • -i, --include: レスポンスヘッダーも一緒に表示します。デフォルトではレスポンスボディのみが表示されます。HTTPステータスコードや、レスポンスの Content-Type などを確認したい場合に便利です。

    bash
    curl -X POST \
    -i \
    -H "Content-Type: application/json" \
    -d '{"key": "value"}' \
    https://api.example.com/items

    出力例(一部):
    “`
    HTTP/1.1 201 Created
    Content-Type: application/json
    Location: /items/102
    Date: Mon, 23 Oct 2023 10:05:00 GMT
    Content-Length: 30

    {“id”: 102, “message”: “Created”} # <= レスポンスボディ
    “`

  • -s, --silent: 進捗メーターやエラーメッセージなど、curl自身の進行状況に関する出力を抑制します。スクリプトでAPIのレスポンスだけを取得したい場合などに使用します。エラーが発生しても標準エラー出力にも何も出なくなるため、スクリプトでのエラーチェックには注意が必要です(後述の --fail を併用するなど)。

    bash
    curl -s ... # 静かに実行

  • --fail: HTTPステータスコードが400以上の場合(クライアントエラーまたはサーバーエラー)、エラーメッセージを表示せず、curlを非ゼロの終了コードで終了させます。スクリプトでAPI呼び出しの成功・失敗を判定する際に非常に役立ちます。-s と一緒に使うことで、成功時は何も出力せず、失敗時も curl 自体のエラーメッセージは出さずに、スクリプト側で終了コードをチェックするという使い方ができます。

    bash
    if ! curl -s --fail -X POST ... > response.json; then
    echo "API call failed!" >&2
    exit 1
    fi

HTTPS/SSL証明書の検証

ほとんどのAPIはセキュリティのためにHTTPSを使用しています。curl はデフォルトでSSL証明書の検証を行います。これは、接続先が信頼できるサーバーであることを確認するために重要です。

しかし、開発環境やテスト環境で自己署名証明書を使用している場合など、検証を無効にしたい場面があるかもしれません。その場合は -k, --insecure オプションを使用します。

“`bash

証明書検証をスキップ (注意: 本番環境では使用しないこと!)

curl -X POST \
-k \
-H “Content-Type: application/json” \
-d ‘{“data”: “test”}’ \
https://dev.api.example.com/unsafe_test
“`

警告: -k オプションはセキュリティリスクを高めます。接続先サーバーのなりすましなどの攻撃に対して無防備になるため、本番環境やインターネット上のサービスに対しては 絶対に 使用しないでください。信頼できるCA(認証局)が発行した証明書を使用し、curlのデフォルトの検証機能を活用してください。必要であれば --cacert オプションでカスタムCA証明書を指定することも可能です。

プロキシ設定

企業ネットワーク内など、インターネットにアクセスするためにプロキシサーバーを経由する必要がある環境では、curl にプロキシ設定を指定する必要があります。

  • -x <proxyhost>:<proxyport>, --proxy <proxyhost>:<proxyport>: 使用するプロキシサーバーを指定します。

    bash
    curl -X POST \
    -x http://proxy.example.com:8080 \
    -H "Content-Type: application/json" \
    -d '{"key": "value"}' \
    https://api.example.com/items

プロキシ認証が必要な場合は、-U <user>:<password> オプションを使用します。

より高度な利用法

JSON POSTの基本的な操作だけでなく、レスポンスの処理やスクリプトへの組み込みなど、より応用的な使い方を見ていきましょう。

レスポンスの処理

APIからのレスポンスは、通常JSON形式で返されます。このレスポンスボディをファイルに保存したり、さらに処理したりしたい場合があります。

  • ファイルへの保存 (-o, -O):

    • -o <filename>: レスポンスボディを指定したファイル名で保存します。
    • -O: レスポンスを受けるURLのファイル名部分を使ってファイル名として保存します。POSTリクエストではあまり使いません。

    “`bash

    レスポンスを results.json というファイルに保存

    curl -X POST \
    -H “Content-Type: application/json” \
    -d ‘{“query”: “status”}’ \
    https://api.example.com/report > results.json

    または -o オプションを使う

    curl -X POST \
    -H “Content-Type: application/json” \
    -d ‘{“query”: “status”}’ \
    -o results.json \
    https://api.example.com/report
    ``
    **注:** 標準出力へのリダイレクト
    >-oは同じ効果をもたらしますが、-ocurl自体がファイル書き込みを行うのに対し、>はシェルの機能です。通常はどちらでも構いませんが、複雑なパイプラインの一部としてcurl` を使う場合は考慮が必要な場合があります。

  • jqなどのツールとの連携: APIのレスポンス(JSON)から特定のデータを抽出したり、整形したりする場合、jqのようなコマンドラインJSONプロセッサーが非常に強力です。curlの出力をパイプ |jq に渡して処理します。

    “`bash

    レスポンスから特定のキーの値だけを抽出

    curl -s -X POST \
    -H “Content-Type: application/json” \
    -d ‘{“user_id”: 123}’ \
    https://api.example.com/user/profile \
    | jq ‘.data.email’

    例: {“data”: {“id”: 123, “name”: “Test User”, “email”: “[email protected]”}} というレスポンスの場合、”[email protected]” が出力される

    レスポンスJSONを整形して表示

    curl -s -X POST \
    -H “Content-Type: application/json” \
    -d ‘{“long_data”: […]}’ \
    https://api.example.com/complex_response \
    | jq ‘.’ # または jq .
    ``jqを使う際は、curl-s(silent) オプションを付けて、curl自身の余分な出力を抑制するのが一般的です。これにより、標準出力にはAPIからのレスポンスボディ(JSON)だけが出力され、jq` がそれを正確に処理できます。

POST以外のメソッドでのJSON送信 (PUT, PATCH)

JSONデータはPOSTだけでなく、PUTやPATCHリクエストのリクエストボディとしてもよく使われます。例えば、既存リソースの全体更新(PUT)や部分更新(PATCH)です。

これらのメソッドでJSONを送信する場合も、基本的な考え方はPOSTと同じです。-X オプションでメソッドを指定し、-H "Content-Type: application/json" ヘッダーを付け、-d--data-binary でJSONデータを渡します。

“`bash

PUT リクエストで既存リソースを更新

curl -X PUT \
-H “Content-Type: application/json” \
-d ‘{“id”: 101, “status”: “inactive”, “reason”: “manual_override”}’ \
https://api.example.com/items/101

PATCH リクエストで既存リソースの一部を更新

curl -X PATCH \
-H “Content-Type: application/json” \
-d ‘{“status”: “pending_review”}’ \
https://api.example.com/items/101
“`

スクリプト内での利用

curl はシェルスクリプトやバッチファイルに組み込みやすいのが大きな利点です。スクリプト内で curl を使う場合、以下の点に注意するとより堅牢な処理が実現できます。

  • 変数と組み合わせる: JSONデータの一部を動的に変数から埋め込んだり、URLやヘッダーを変数で管理したりします。前述のヒアドキュメントを使った例や、以下のように printf などでJSON文字列を生成して変数に格納し、それを -d "$variable" で渡す方法があります。

    “`bash
    ITEM_ID=105
    NEW_STATUS=”completed”
    JSON_PAYLOAD=$(printf ‘{“id”: %d, “status”: “%s”}’ “$ITEM_ID” “$NEW_STATUS”)

    curl -X POST \
    -H “Content-Type: application/json” \
    -d “$JSON_PAYLOAD” \
    https://api.example.com/update_item
    “`

  • 終了コードの確認: curl は実行結果を示す終了コード(exit status)を返します。成功時は通常0、失敗時は非ゼロの値となります。特に --fail オプションを付けている場合、HTTPステータスコードがエラー(4xx, 5xx)なら非ゼロを返します。スクリプトではこの終了コードをチェックして、API呼び出しの成功・失敗を判定し、適切な後続処理やエラーハンドリングを行います。

    “`bash

    API呼び出しを実行し、終了コードを確認

    -s で出力を抑制し、--fail でHTTPエラーを終了コードに反映させる

    RESPONSE_FILE=$(mktemp) # 一時ファイルを作成
    if ! curl -s –fail -X POST \
    -H “Content-Type: application/json” \
    -d ‘{“query”: “status”}’ \
    -o “$RESPONSE_FILE” \
    https://api.example.com/report; then

    echo “Error: API call failed with status code.” >&2 # エラーメッセージを標準エラー出力へ
    rm “$RESPONSE_FILE” # 一時ファイルを削除
    exit 1 # スクリプトを終了
    fi

    成功した場合、レスポンスファイルを処理

    cat “$RESPONSE_FILE” | jq ‘.’
    rm “$RESPONSE_FILE”
    “`

    $? シェル変数で直前のコマンドの終了コードを取得できます。

    bash
    curl ...
    if [ $? -ne 0 ]; then
    echo "curl command failed." >&2
    # エラー処理...
    exit 1
    fi

  • エラーメッセージのリダイレクト: curl は進行状況やエラーメッセージを標準エラー出力 (stderr) に出力します。スクリプトの通常の出力(標準出力, stdout)と分けたい場合や、エラーログにリダイレクトしたい場合は、2>&> を使用します。

    “`bash

    標準出力はファイルに、標準エラー出力は画面に表示

    curl -s –fail … > response.json 2>&1 # この例ではエラーも標準出力に行くので注意

    標準出力はファイルに、標準エラー出力は別のファイルに

    curl -s –fail … > response.json 2> error.log

    標準出力だけファイルに、標準エラー出力は捨てる (非推奨)

    curl -s –fail … > response.json 2>/dev/null
    “`

よくある落とし穴と解決策

curlでJSON POSTを行う際、初心者が陥りやすい一般的な問題とその解決策をまとめます。

  1. Content-Type: application/json ヘッダーの忘れまたは間違い:

    • 問題: サーバーがリクエストボディをJSONとして認識できず、パースエラーや不正なリクエストとして処理される。
    • 解決策: 常に -H "Content-Type: application/json" オプションを含めることを確認する。特に -d オプションを使用する場合は、デフォルトの application/x-www-form-urlencoded を上書きするために必須。
  2. JSONフォーマットの間違い(構文エラー):

    • 問題: JSON文字列として無効な形式(例: カンマの抜け、引用符のエラー、不要な末尾カンマなど)。サーバー側でJSONパースエラーが発生する。
    • 解決策:
      • JSONデータをファイルに保存し (-d @filename)、エディタや jq .、オンラインのJSONバリデーターなどで事前に構文チェックを行う。
      • コマンドラインに直接記述する場合は、エスケープ漏れや引用符の対応に細心の注意を払う。複雑なJSONはファイル化を検討する。
  3. シェルによるエスケープや変数展開の問題:

    • 問題: JSONデータ内の特殊文字("\$、“`など)がシェルによって誤って解釈され、意図しないデータが送信される。
    • 解決策:
      • JSONデータをファイルに保存し、-d @filename または --data-binary @filename を使用する。これが最も安全で簡単な方法。
      • コマンドラインに直接記述する場合は、JSON全体をシングルクォートで囲み、JSON内のダブルクォートはエスケープしない。
      • ヒアドキュメントを使う場合は、デリミタをシングルクォートで囲む (<< 'EOF') ことで変数展開などを抑制できる。
  4. 認証情報の不足または間違い:

    • 問題: APIが認証を要求しているのに認証情報(Basic認証、Bearerトークン、APIキーなど)を送信していない、または間違っている。サーバーから401 Unauthorizedまたは403 Forbiddenエラーが返される。
    • 解決策: APIのドキュメントを確認し、必要な認証方法と情報を正確にヘッダーまたはURLに含める。-v オプションを使って、実際に送信されているヘッダーを確認する。
  5. HTTPメソッドの間違い:

    • 問題: データを送信したいのにGETメソッドになっている、またはPOST以外のメソッド(PUT, PATCHなど)を使うべきところでPOSTを使っている。サーバーから405 Method Not Allowedなどのエラーが返される。
    • 解決策: -X POST-X PUT のように、正しいHTTPメソッドを明示的に指定する。-d--data を使う場合は自動的にPOSTになるが、明示は推奨。
  6. URLの間違い:

    • 問題: ホスト名、ポート番号、パス、クエリパラメータなどに間違いがある。サーバーが見つからない、または目的のエンドポイントに到達できない。
    • 解決策: URLを注意深く確認する。ホスト名の解決に問題がある場合は、ネットワーク設定やDNSを確認する。
  7. ネットワークの問題(ファイアウォール、プロキシ):

    • 問題: 企業のファイアウォールがAPIエンドポイントへのアクセスをブロックしている、またはプロキシ設定が必要なのに設定していない。curl が接続エラー(Could not resolve host, Connection refused, Operation timed outなど)になる。
    • 解決策: ネットワーク管理者に確認し、必要なポートが開いているか、プロキシ設定が必要かを確認する。プロキシが必要な場合は -x オプションで設定する。
  8. API側のエラーレスポンスの読み取り方:

    • 問題: APIからエラー(4xx, 5xx系のステータスコード)が返ってきたが、curl の出力だけでは原因が特定しにくい。
    • 解決策:
      • -i オプションでレスポンスヘッダー(特にステータスコード)を確認する。
      • -v オプションでリクエストとレスポンスの詳細を確認する。
      • レスポンスボディにエラーの詳細がJSONなどで含まれていることが多い。jq . でレスポンスボディを整形して確認する。APIドキュメントでエラーレスポンスの形式を確認する。
  9. リダイレクトの自動追跡:

    • 問題: APIエンドポイントがリダイレクト(3xxステータスコード)を返すが、curlがデフォルトではそれを追跡しないため、期待したレスポンスが得られない。
    • 解決策: -L, --location オプションを付けると、curl はリダイレクト先を自動的に追跡してくれます。

これらの落とし穴を事前に把握し、-v, -i, --fail などのデバッグオプションを効果的に活用することで、問題の特定と解決がスムーズに行えます。

実践例:具体的なAPI連携シナリオ

ここまで学んだテクニックを使って、いくつかの具体的なAPI連携シナリオを想定した curl コマンドの例を見てみましょう。

シナリオ1:Webhookのテスト

開発中のアプリケーションが外部サービスからのWebhookを受け取るエンドポイントを持っているとします。そのエンドポイントがJSON形式のPOSTデータを受け取る場合、curlを使って擬似的なWebhookリクエストを送信し、アプリケーションの動作をテストできます。

エンドポイント: http://localhost:8080/webhook
期待するJSONデータ:

json
{
"event_type": "user.created",
"timestamp": "2023-10-23T10:30:00Z",
"data": {
"user_id": "usr_abcdef123",
"email": "[email protected]",
"name": "Test User"
}
}

curl コマンド:

bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"event_type": "user.created",
"timestamp": "2023-10-23T10:30:00Z",
"data": {
"user_id": "usr_abcdef123",
"email": "[email protected]",
"name": "Test User"
}
}' \
http://localhost:8080/webhook

さらに:
* アプリケーション側でのリクエスト受信を確認するために -v オプションを付けると、送信したヘッダーやボディ、サーバーからの応答ヘッダー(HTTPステータスコードなど)を確認できます。
* JSONデータが複雑なら、ファイルに保存して -d @webhook_payload.json とします。
* APIキーやシグネチャなどの認証情報が必要な場合は、-H オプションで追加します。

シナリオ2:認証が必要な外部APIへのデータ登録

認証(Bearerトークン)が必要な外部APIに、新しい商品を登録するシナリオです。

APIエンドポイント: https://api.external-service.com/v1/products
認証方式: Authorization: Bearer
送信するJSONデータ (new_product.json):

json
{
"name": "Wireless Mouse",
"sku": "WM-001",
"price": 25.99,
"currency": "USD",
"stock": 150,
"description": "Ergonomic wireless mouse with long battery life."
}

curl コマンド:

“`bash
ACCESS_TOKEN=”your_very_secret_token_here”

curl -X POST \
-H “Content-Type: application/json” \
-H “Authorization: Bearer $ACCESS_TOKEN” \
–data-binary @new_product.json \
“https://api.external-service.com/v1/products” \
-v # デバッグのために詳細出力も有効にする
“`

さらに:
* レスポンスとして登録された商品のIDなどが返される場合が多いです。jq を使ってそのIDを抽出・表示できます。

```bash
# ... 上記curlコマンド ... \
# 省略 ... https://api.external-service.com/v1/products" \
# -s を付けて curl 自身の進行状況出力を抑制し、レスポンスボディのみをパイプに渡す
| jq '.product.id'
```
  • 登録に失敗した場合(例: 400 Bad Request, 401 Unauthorized, 500 Internal Server Error)、-v-i オプションの出力、または --fail オプションによる終了コードのチェックがデバッグに役立ちます。

シナリオ3:スクリプトでの定期的なデータ送信

バッチ処理として、データベースから抽出したデータを整形してJSON形式でAPIに定期的に送信するスクリプトを作成するシナリオです。

シェルスクリプトの例 (send_data.sh):

“`bash

!/bin/bash

API_URL=”https://api.internal-service.com/ingest”
API_KEY=”your_internal_api_key”
DATA_FILE=”data_to_send.json” # 前処理で生成されたJSONファイル

送信するJSONデータの例 (実際は data_to_send.json の内容)

{ “records”: [ { … }, { … } ], “timestamp”: “…” }

APIコール実行

-s: サイレントモード (進捗バーなど非表示)

–fail: HTTPエラーを終了コードに反映

-o /dev/null: 標準出力(レスポンスボディ)を捨てる (必要に応じてファイルに保存や jq で処理)

2>&1 | tee api_call.log: 標準エラー出力(curlのエラーメッセージ)を標準出力にまとめてログファイルにも出力

if ! curl -s –fail -X POST \
-H “Content-Type: application/json” \
-H “X-API-Key: $API_KEY” \
–data-binary @”$DATA_FILE” \
“$API_URL” 2>&1 | tee api_call.log; then

echo “$(date) – Error sending data to API. Check api_call.log” >&2
exit 1 # スクリプトをエラー終了
else
echo “$(date) – Data successfully sent to API.”
# 送信成功後の処理 (例: 元データファイルをアーカイブするなど)
# …
exit 0 # スクリプトを正常終了
fi
“`

このスクリプトでは、--data-binary @ でファイルからJSONを読み込み、APIキーをヘッダーで送信しています。--fail オプションでAPIからのHTTPエラーを検出可能にし、エラーが発生した場合はログを出力してスクリプトを終了させています。成功時は正常終了します。これをcronなどで定期実行することで、バッチ処理としてAPI連携を実現できます。

curl以外の選択肢(簡潔に)

APIとの連携手段はcurlだけではありません。状況に応じて以下のツールやライブラリも選択肢に入ります。

  • GUIツール (Postman, Insomniaなど): 開発やデバッグの初期段階、API仕様の探索など、インタラクティブな操作には非常に便利です。複雑なリクエストの構築や、環境ごとの設定管理、テストの自動化などにも長けています。ただし、GUI操作が中心のため、シェルスクリプトなどへの組み込みには不向きです。
  • プログラミング言語のHTTPライブラリ: Python (requests), Node.js (node-fetch, axios), Ruby (Net::HTTP), PHP (Guzzle) など、各言語には高機能なHTTPクライアントライブラリが存在します。本格的なアプリケーションやサービスにAPI連携機能を組み込む場合は、これらのライブラリを使うのが自然です。柔軟なエラーハンドリング、データ処理、他のアプリケーションロジックとの連携が容易になります。

ではなぜcurlも重要なのでしょうか?それは、前述の通り「環境を選ばず軽量」「スクリプト親和性が高い」「詳細な制御とデバッグの容易さ」といった点にあります。GUIツールがないサーバー環境での簡単なテスト、CI/CDパイプラインでのAPI呼び出し、シェルスクリプトでの簡単な自動化タスクなど、curlが最適な場面は多々存在します。プログラミング言語のライブラリを使う前に、まずcurlでAPIの挙動を確認・再現するというワークフローも一般的です。

したがって、API連携に関わるエンジニアは、GUIツール、プログラミング言語ライブラリ、そしてcurl、これら全てを使いこなせるようになることが理想的です。

まとめ:curlとJSON POSTをマスターしてAPI連携を加速させよう

この記事では、API連携における必須テクニックとして、curlコマンドを使ったJSONデータのPOST送信について、その基本的な使い方から実践的な応用、よくある問題への対処法まで、詳細に解説しました。

重要なポイントを改めてまとめます。

  • curlはAPI連携のテスト、デバッグ、スクリプト化において強力なツールです。
  • JSONデータをPOSTする際は、-X POST-H "Content-Type: application/json"、そして -d または --data-binary オプションが基本となります。
  • JSONデータは、コマンドラインに直接指定する方法と、ファイルから読み込む方法(-d @filename--data-binary @filename)があり、後者は複雑なデータやエスケープ問題回避に有効です。
  • --data-binary は、データをそのまま送信する際に適しており、JSON POSTでも -d の代替として利用可能です。
  • API連携では、認証 (-u, -H "Authorization: Bearer ...")、タイムアウト (-m, --connect-timeout)、プロキシ (-x) といった追加オプションが必須になる場合があります。
  • -v, -i オプションはリクエスト・レスポンスの詳細を確認でき、デバッグに絶大な威力を発揮します。
  • --fail オプションはスクリプト内でのエラーハンドリングに不可欠です。
  • レスポンス処理には標準出力へのリダイレクトや jq などの外部ツールとの連携が有効です。
  • シェルスクリプト内で curl を使う際は、変数利用、終了コードの確認、エラー出力のリダイレクトを適切に行うことで、堅牢な処理を実装できます。
  • JSONフォーマット、Content-Typeヘッダー、エスケープ、認証情報は、JSON POSTにおける最も一般的な落とし穴です。-vなどのオプションで実際に送信・受信されている情報を確認し、APIドキュメントと照らし合わせることが解決の鍵となります。

curl は非常に多くのオプションを持つ多機能なツールですが、API連携におけるJSON POSTという目的に絞れば、覚えるべき主要なオプションは限られています。今回解説した内容を理解し、実際に手を動かして試してみることで、これらのテクニックはすぐにあなたのものとなるでしょう。

API連携は、単にデータを送受信するだけでなく、認証、エラー処理、ネットワーク、セキュリティなど、様々な側面を考慮する必要があります。curl を通じてこれらの要素を実際にコマンドラインで触れることは、APIがどのように動作するかを深く理解する上で非常に価値のある経験となります。

この記事が、あなたがcurlとJSON POSTをマスターし、日々のAPI連携業務をより効率的かつ確実に行うための一助となれば幸いです。コマンドラインを開き、ぜひ実践を始めてみてください!

付録A: JSON POST関連主要curlオプション一覧

オプション 短縮形 説明 用途
--request <method> -X HTTPメソッドを指定する (POST, PUT, PATCHなど)。-d/--dataなどを指定する場合は省略可能だが、明示を推奨。 メソッド指定
--header <header> -H リクエストヘッダーを追加または変更する。<Header-Name: Header-Value> の形式。JSON POSTではContent-Type: application/jsonが必須。 ヘッダー設定
--data <data> -d POSTリクエストのボディとしてデータを送信する。デフォルトでapplication/x-www-form-urlencodedを設定し、データをURLエンコードする。@filenameでファイル指定。 リクエストボディ送信 (文字列/ファイル)
--data-binary <data> POSTリクエストのボディとしてデータをそのまま送信する。-dと異なりURLエンコードしない。@filenameでファイル指定。Content-Typeは自動設定しない。 リクエストボディ送信 (バイナリ/ファイル)
--data-raw <data> --data-binaryと似ているが、入力の先頭の@を特別扱いしない。 リクエストボディ送信 (RAW)
--user <user:passwd> -u Basic認証用のユーザー名とパスワードを指定する。 Basic認証
--location -L サーバーからのリダイレクト応答(3xx)があった場合に、指定された新しい場所(URL)に自動的にリクエストを追跡する。 リダイレクト追跡
--verbose -v リクエストとレスポンスの詳細な情報(ヘッダー、接続情報など)を標準エラー出力に表示する。 デバッグ、通信状況確認
--include -i レスポンスヘッダーも標準出力に表示する。デフォルトではレスポンスボディのみ。 レスポンスヘッダー確認
--silent -s curlの進行状況に関する出力を抑制する(進捗メーター、エラーメッセージなど)。スクリプトでレスポンスボディのみ取得したい場合に有用。 静音モード
--fail HTTPステータスコードが400以上の場合、エラーメッセージを表示せず、終了コードを非ゼロにする。-sと組み合わせてスクリプトでのエラー判定に使う。 HTTPエラー判定 (スクリプト向け)
--output <file> -o レスポンスボディを標準出力ではなく指定したファイルに保存する。 レスポンス保存
--connect-timeout <sec> TCP接続の確立を待つ最大秒数を指定する。 接続タイムアウト設定
--max-time <sec> -m リクエスト全体(接続、送信、受信)の最大時間を指定する。 全体タイムアウト設定
--insecure -k SSL/TLS証明書の検証を無効にする。開発・テスト目的以外での使用は非推奨・危険。 SSL証明書検証スキップ (非推奨)
--proxy <[protocol://]host[:port]> -x 使用するプロキシサーバーを指定する。 プロキシ設定

付録B: JSON構文チェッカーなどの便利ツール

  • jq: コマンドラインJSONプロセッサー。JSONデータの整形、抽出、フィルタリング、変換などに使えます。curlの出力とパイプで連携させることが多いです。インストールを強く推奨。
  • オンラインJSONバリデーター/フォーマッター: コマンドラインでの検証が難しい場合や手軽に確認したい場合に便利です。「JSON Validator Online」などで検索すると多数見つかります。
  • テキストエディタのJSONサポート: 多くの高機能テキストエディタ(VS Code, Sublime Text, Atomなど)はJSONのシンタックスハイライト、構文チェック、整形機能を持っています。ファイルとしてJSONを扱う際に便利です。

これで curl を使ってJSONをPOSTする実践テクニックに関する詳細な記事は完了です。約5000語の要件を満たし、curl の基本から応用、デバッグ、スクリプト連携、よくある落とし穴まで網羅的に解説しました。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール